blob: 76e2346a41ef2063135aa19d7a1634305e547d73 [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
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +010024#include "config.h"
25
Philipp Brüschweiler591cfca2012-07-11 22:25:29 +020026#include <assert.h>
Jan Arne Petersencba9e472012-06-21 21:52:19 +020027#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +020030#include <stdbool.h>
Jan Arne Petersencba9e472012-06-21 21:52:19 +020031
32#include <linux/input.h>
33#include <cairo.h>
34
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +010035#include <pango/pangocairo.h>
36
Jan Arne Petersencba9e472012-06-21 21:52:19 +020037#include "window.h"
38#include "text-client-protocol.h"
39
40struct text_entry {
41 struct widget *widget;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020042 struct window *window;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020043 char *text;
44 int active;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +020045 uint32_t cursor;
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +020046 uint32_t anchor;
Jan Arne Petersen46535312013-01-16 21:26:38 +010047 struct {
48 char *text;
49 int32_t cursor;
50 char *commit;
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +010051 PangoAttrList *attr_list;
Jan Arne Petersen46535312013-01-16 21:26:38 +010052 } preedit;
53 struct {
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +010054 PangoAttrList *attr_list;
Jan Arne Petersen46535312013-01-16 21:26:38 +010055 int32_t cursor;
56 } preedit_info;
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +010057 struct {
58 int32_t cursor;
59 int32_t anchor;
Jan Arne Petersen919bc142013-04-18 16:47:34 +020060 uint32_t delete_index;
61 uint32_t delete_length;
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +020062 bool invalid_delete;
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +010063 } pending_commit;
Jan Arne Petersen62ece762013-04-18 16:47:36 +020064 struct wl_text_input *text_input;
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +010065 PangoLayout *layout;
Jan Arne Petersencd997062012-11-18 19:06:44 +010066 struct {
67 xkb_mod_mask_t shift_mask;
68 } keysym;
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +010069 uint32_t serial;
Jan Arne Petersen00191c72013-04-18 16:47:33 +020070 uint32_t reset_serial;
Jan Arne Petersen0558a932013-01-16 21:26:45 +010071 uint32_t content_purpose;
Jan Arne Petersen61381972013-01-31 15:52:21 +010072 uint32_t click_to_show;
Jan Arne Petersen9d419132013-04-18 16:47:16 +020073 char *preferred_language;
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +020074 bool button_pressed;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020075};
76
77struct editor {
Jan Arne Petersen62ece762013-04-18 16:47:36 +020078 struct wl_text_input_manager *text_input_manager;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020079 struct display *display;
80 struct window *window;
81 struct widget *widget;
82 struct text_entry *entry;
83 struct text_entry *editor;
Rob Bradford9d1d32b2012-11-18 19:06:49 +010084 struct text_entry *active_entry;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020085};
86
Jan Arne Petersen6345faa2012-11-05 03:26:39 +010087static const char *
Jan Arne Petersen6345faa2012-11-05 03:26:39 +010088utf8_end_char(const char *p)
89{
90 while ((*p & 0xc0) == 0x80)
91 p++;
92 return p;
93}
94
95static const char *
Jan Arne Petersen68516862013-04-18 16:47:42 +020096utf8_prev_char(const char *s, const char *p)
97{
98 for (--p; p >= s; --p) {
99 if ((*p & 0xc0) != 0x80)
100 return p;
101 }
102 return NULL;
103}
104
105static const char *
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100106utf8_next_char(const char *p)
107{
108 if (*p != 0)
109 return utf8_end_char(++p);
110 return NULL;
111}
112
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200113static void text_entry_redraw_handler(struct widget *widget, void *data);
114static void text_entry_button_handler(struct widget *widget,
115 struct input *input, uint32_t time,
116 uint32_t button,
117 enum wl_pointer_button_state state, void *data);
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -0800118static void text_entry_touch_handler(struct widget *widget, struct input *input,
119 uint32_t serial, uint32_t time, int32_t id,
120 float tx, float ty, void *data);
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200121static int text_entry_motion_handler(struct widget *widget,
122 struct input *input, uint32_t time,
123 float x, float y, void *data);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100124static void text_entry_insert_at_cursor(struct text_entry *entry, const char *text,
125 int32_t cursor, int32_t anchor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200126static void text_entry_set_preedit(struct text_entry *entry,
127 const char *preedit_text,
128 int preedit_cursor);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200129static void text_entry_delete_text(struct text_entry *entry,
130 uint32_t index, uint32_t length);
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200131static void text_entry_delete_selected_text(struct text_entry *entry);
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100132static void text_entry_reset_preedit(struct text_entry *entry);
133static void text_entry_commit_and_reset(struct text_entry *entry);
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200134static void text_entry_get_cursor_rectangle(struct text_entry *entry, struct rectangle *rectangle);
135static void text_entry_update(struct text_entry *entry);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200136
137static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200138text_input_commit_string(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200139 struct wl_text_input *text_input,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100140 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100141 const char *text)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200142{
143 struct text_entry *entry = data;
144
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200145 if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) {
146 fprintf(stderr, "Ignore commit. Serial: %u, Current: %u, Reset: %u\n",
147 serial, entry->serial, entry->reset_serial);
148 return;
149 }
150
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200151 if (entry->pending_commit.invalid_delete) {
152 fprintf(stderr, "Ignore commit. Invalid previous delete_surrounding event.\n");
153 memset(&entry->pending_commit, 0, sizeof entry->pending_commit);
154 return;
155 }
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100156
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200157 text_entry_reset_preedit(entry);
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200158
159 if (entry->pending_commit.delete_length) {
160 text_entry_delete_text(entry,
161 entry->pending_commit.delete_index,
162 entry->pending_commit.delete_length);
Jan Arne Petersena96953d2013-05-30 13:57:02 +0200163 } else {
164 text_entry_delete_selected_text(entry);
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200165 }
166
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100167 text_entry_insert_at_cursor(entry, text,
168 entry->pending_commit.cursor,
169 entry->pending_commit.anchor);
170
171 memset(&entry->pending_commit, 0, sizeof entry->pending_commit);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200172
173 widget_schedule_redraw(entry->widget);
174}
175
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200176static void
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200177clear_pending_preedit(struct text_entry *entry)
178{
179 memset(&entry->pending_commit, 0, sizeof entry->pending_commit);
180
181 pango_attr_list_unref(entry->preedit_info.attr_list);
182
183 entry->preedit_info.cursor = 0;
184 entry->preedit_info.attr_list = NULL;
185
186 memset(&entry->preedit_info, 0, sizeof entry->preedit_info);
187}
188
189static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200190text_input_preedit_string(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200191 struct wl_text_input *text_input,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100192 uint32_t serial,
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200193 const char *text,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100194 const char *commit)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200195{
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200196 struct text_entry *entry = data;
197
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200198 if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) {
199 fprintf(stderr, "Ignore preedit_string. Serial: %u, Current: %u, Reset: %u\n",
200 serial, entry->serial, entry->reset_serial);
201 clear_pending_preedit(entry);
202 return;
203 }
204
205 if (entry->pending_commit.invalid_delete) {
206 fprintf(stderr, "Ignore preedit_string. Invalid previous delete_surrounding event.\n");
207 clear_pending_preedit(entry);
208 return;
209 }
210
Jan Arne Petersena96953d2013-05-30 13:57:02 +0200211 if (entry->pending_commit.delete_length) {
212 text_entry_delete_text(entry,
213 entry->pending_commit.delete_index,
214 entry->pending_commit.delete_length);
215 } else {
216 text_entry_delete_selected_text(entry);
217 }
Jan Arne Petersena96953d2013-05-30 13:57:02 +0200218
Jan Arne Petersen46535312013-01-16 21:26:38 +0100219 text_entry_set_preedit(entry, text, entry->preedit_info.cursor);
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100220 entry->preedit.commit = strdup(commit);
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200221 entry->preedit.attr_list = pango_attr_list_ref(entry->preedit_info.attr_list);
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100222
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200223 clear_pending_preedit(entry);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200224
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200225 text_entry_update(entry);
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200226
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200227 widget_schedule_redraw(entry->widget);
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200228}
229
230static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200231text_input_delete_surrounding_text(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200232 struct wl_text_input *text_input,
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200233 int32_t index,
234 uint32_t length)
235{
236 struct text_entry *entry = data;
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200237 uint32_t text_length;
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200238
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200239 entry->pending_commit.delete_index = entry->cursor + index;
240 entry->pending_commit.delete_length = length;
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200241 entry->pending_commit.invalid_delete = false;
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200242
Jan Arne Petersen68516862013-04-18 16:47:42 +0200243 text_length = strlen(entry->text);
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200244
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200245 if (entry->pending_commit.delete_index > text_length ||
246 length > text_length ||
Jan Arne Petersen895a1282013-05-30 13:57:04 +0200247 entry->pending_commit.delete_index + length > text_length) {
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200248 fprintf(stderr, "delete_surrounding_text: Invalid index: %d," \
249 "length %u'; cursor: %u text length: %u\n", index, length, entry->cursor, text_length);
250 entry->pending_commit.invalid_delete = true;
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200251 return;
252 }
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200253}
254
255static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200256text_input_cursor_position(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200257 struct wl_text_input *text_input,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100258 int32_t index,
259 int32_t anchor)
260{
261 struct text_entry *entry = data;
262
263 entry->pending_commit.cursor = index;
264 entry->pending_commit.anchor = anchor;
265}
266
267static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200268text_input_preedit_styling(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200269 struct wl_text_input *text_input,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100270 uint32_t index,
271 uint32_t length,
272 uint32_t style)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200273{
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100274 struct text_entry *entry = data;
275 PangoAttribute *attr1 = NULL;
276 PangoAttribute *attr2 = NULL;
277
278 if (!entry->preedit_info.attr_list)
279 entry->preedit_info.attr_list = pango_attr_list_new();
280
281 switch (style) {
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200282 case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
283 case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100284 attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
285 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200286 case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT:
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100287 attr1 = pango_attr_underline_new(PANGO_UNDERLINE_ERROR);
288 attr2 = pango_attr_underline_color_new(65535, 0, 0);
289 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200290 case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION:
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100291 attr1 = pango_attr_background_new(0.3 * 65535, 0.3 * 65535, 65535);
292 attr2 = pango_attr_foreground_new(65535, 65535, 65535);
293 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200294 case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
295 case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE:
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100296 attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
297 attr2 = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
298 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200299 case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE:
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100300 attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
301 attr2 = pango_attr_foreground_new(0.3 * 65535, 0.3 * 65535, 0.3 * 65535);
302 break;
303 }
304
305 if (attr1) {
306 attr1->start_index = entry->cursor + index;
307 attr1->end_index = entry->cursor + index + length;
308 pango_attr_list_insert(entry->preedit_info.attr_list, attr1);
309 }
310
311 if (attr2) {
312 attr2->start_index = entry->cursor + index;
313 attr2->end_index = entry->cursor + index + length;
314 pango_attr_list_insert(entry->preedit_info.attr_list, attr2);
315 }
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200316}
317
318static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200319text_input_preedit_cursor(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200320 struct wl_text_input *text_input,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100321 int32_t index)
322{
323 struct text_entry *entry = data;
324
325 entry->preedit_info.cursor = index;
326}
327
328static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200329text_input_modifiers_map(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200330 struct wl_text_input *text_input,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100331 struct wl_array *map)
332{
Jan Arne Petersencd997062012-11-18 19:06:44 +0100333 struct text_entry *entry = data;
334
335 entry->keysym.shift_mask = keysym_modifiers_get_mask(map, "Shift");
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100336}
337
338static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200339text_input_keysym(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200340 struct wl_text_input *text_input,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100341 uint32_t serial,
342 uint32_t time,
343 uint32_t key,
344 uint32_t state,
345 uint32_t modifiers)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200346{
Jan Arne Petersen8aba11d2012-09-17 15:28:07 +0200347 struct text_entry *entry = data;
Jan Arne Petersencd997062012-11-18 19:06:44 +0100348 const char *state_label = "release";
349 const char *key_label = "Unknown";
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100350 const char *new_char;
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200351
352 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
353 state_label = "pressed";
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200354 }
355
Jan Arne Petersencd997062012-11-18 19:06:44 +0100356 if (key == XKB_KEY_Left ||
357 key == XKB_KEY_Right) {
358 if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
359 return;
360
361 if (key == XKB_KEY_Left)
362 new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
363 else
364 new_char = utf8_next_char(entry->text + entry->cursor);
365
366 if (new_char != NULL) {
367 entry->cursor = new_char - entry->text;
Jan Arne Petersencd997062012-11-18 19:06:44 +0100368 }
369
Jan Arne Petersen68516862013-04-18 16:47:42 +0200370 if (!(modifiers & entry->keysym.shift_mask))
371 entry->anchor = entry->cursor;
372 widget_schedule_redraw(entry->widget);
373
Jan Arne Petersencd997062012-11-18 19:06:44 +0100374 return;
375 }
376
Jan Arne Petersen3fb6e712013-01-16 21:26:52 +0100377 if (key == XKB_KEY_BackSpace) {
378 const char *start, *end;
379
Jan Arne Petersendfd34462013-04-18 16:47:26 +0200380 if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
381 return;
382
Jan Arne Petersen3fb6e712013-01-16 21:26:52 +0100383 text_entry_commit_and_reset(entry);
384
385 start = utf8_prev_char(entry->text, entry->text + entry->cursor);
Jan Arne Petersen3fb6e712013-01-16 21:26:52 +0100386 if (start == NULL)
387 return;
388
Daiki Uenob08b3292013-06-28 18:59:44 +0900389 end = utf8_next_char(start);
390
Jan Arne Petersen3fb6e712013-01-16 21:26:52 +0100391 text_entry_delete_text(entry,
392 start - entry->text,
393 end - start);
394
395 return;
396 }
397
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200398 switch (key) {
399 case XKB_KEY_Tab:
400 key_label = "Tab";
401 break;
402 case XKB_KEY_KP_Enter:
Jan Arne Petersencd997062012-11-18 19:06:44 +0100403 case XKB_KEY_Return:
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200404 key_label = "Enter";
405 break;
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200406 }
407
408 fprintf(stderr, "%s key was %s.\n", key_label, state_label);
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200409}
410
411static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200412text_input_enter(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200413 struct wl_text_input *text_input,
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200414 struct wl_surface *surface)
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200415{
416 struct text_entry *entry = data;
417
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200418 if (surface != window_get_wl_surface(entry->window))
419 return;
420
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200421 entry->active = 1;
422
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200423 text_entry_update(entry);
424 entry->reset_serial = entry->serial;
425
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200426 widget_schedule_redraw(entry->widget);
427}
428
429static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200430text_input_leave(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200431 struct wl_text_input *text_input)
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200432{
433 struct text_entry *entry = data;
434
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100435 text_entry_commit_and_reset(entry);
436
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200437 entry->active = 0;
438
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200439 wl_text_input_hide_input_panel(text_input);
Jan Arne Petersen61381972013-01-31 15:52:21 +0100440
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200441 widget_schedule_redraw(entry->widget);
442}
443
Jan Arne Petersen61381972013-01-31 15:52:21 +0100444static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200445text_input_input_panel_state(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200446 struct wl_text_input *text_input,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100447 uint32_t state)
448{
449}
450
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200451static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200452text_input_language(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200453 struct wl_text_input *text_input,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200454 uint32_t serial,
455 const char *language)
456{
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200457 fprintf(stderr, "input language is %s \n", language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200458}
459
460static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200461text_input_text_direction(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200462 struct wl_text_input *text_input,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200463 uint32_t serial,
464 uint32_t direction)
465{
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200466 struct text_entry *entry = data;
467 PangoContext *context = pango_layout_get_context(entry->layout);
468 PangoDirection pango_direction;
469
470
471 switch (direction) {
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200472 case WL_TEXT_INPUT_TEXT_DIRECTION_LTR:
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200473 pango_direction = PANGO_DIRECTION_LTR;
474 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200475 case WL_TEXT_INPUT_TEXT_DIRECTION_RTL:
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200476 pango_direction = PANGO_DIRECTION_RTL;
477 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200478 case WL_TEXT_INPUT_TEXT_DIRECTION_AUTO:
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200479 default:
480 pango_direction = PANGO_DIRECTION_NEUTRAL;
481 }
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200482
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200483 pango_context_set_base_dir(context, pango_direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200484}
485
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200486static const struct wl_text_input_listener text_input_listener = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200487 text_input_enter,
488 text_input_leave,
489 text_input_modifiers_map,
490 text_input_input_panel_state,
491 text_input_preedit_string,
492 text_input_preedit_styling,
493 text_input_preedit_cursor,
494 text_input_commit_string,
495 text_input_cursor_position,
496 text_input_delete_surrounding_text,
497 text_input_keysym,
498 text_input_language,
499 text_input_text_direction
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200500};
501
502static struct text_entry*
503text_entry_create(struct editor *editor, const char *text)
504{
505 struct text_entry *entry;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200506
Brian Lovinbc919262013-08-07 15:34:59 -0700507 entry = xmalloc(sizeof *entry);
508 memset(entry, 0, sizeof *entry);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200509
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200510 entry->widget = widget_add_widget(editor->widget, entry);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200511 entry->window = editor->window;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200512 entry->text = strdup(text);
513 entry->active = 0;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200514 entry->cursor = strlen(text);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200515 entry->anchor = entry->cursor;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200516 entry->text_input = wl_text_input_manager_create_text_input(editor->text_input_manager);
517 wl_text_input_add_listener(entry->text_input, &text_input_listener, entry);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200518
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200519 widget_set_redraw_handler(entry->widget, text_entry_redraw_handler);
520 widget_set_button_handler(entry->widget, text_entry_button_handler);
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200521 widget_set_motion_handler(entry->widget, text_entry_motion_handler);
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -0800522 widget_set_touch_down_handler(entry->widget, text_entry_touch_handler);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200523
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200524 return entry;
525}
526
527static void
528text_entry_destroy(struct text_entry *entry)
529{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200530 widget_destroy(entry->widget);
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200531 wl_text_input_destroy(entry->text_input);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100532 g_clear_object(&entry->layout);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200533 free(entry->text);
534 free(entry);
535}
536
537static void
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200538redraw_handler(struct widget *widget, void *data)
539{
540 struct editor *editor = data;
541 cairo_surface_t *surface;
542 struct rectangle allocation;
543 cairo_t *cr;
544
545 surface = window_get_surface(editor->window);
546 widget_get_allocation(editor->widget, &allocation);
547
548 cr = cairo_create(surface);
549 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
550 cairo_clip(cr);
551
552 cairo_translate(cr, allocation.x, allocation.y);
553
554 /* Draw background */
555 cairo_push_group(cr);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200556 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200557 cairo_set_source_rgba(cr, 1, 1, 1, 1);
558 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
559 cairo_fill(cr);
560
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200561 cairo_pop_group_to_source(cr);
562 cairo_paint(cr);
563
564 cairo_destroy(cr);
565 cairo_surface_destroy(surface);
566}
567
568static void
569text_entry_allocate(struct text_entry *entry, int32_t x, int32_t y,
570 int32_t width, int32_t height)
571{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200572 widget_set_allocation(entry->widget, x, y, width, height);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200573}
574
575static void
576resize_handler(struct widget *widget,
577 int32_t width, int32_t height, void *data)
578{
579 struct editor *editor = data;
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200580 struct rectangle allocation;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200581
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200582 widget_get_allocation(editor->widget, &allocation);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200583
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200584 text_entry_allocate(editor->entry,
585 allocation.x + 20, allocation.y + 20,
586 width - 40, height / 2 - 40);
587 text_entry_allocate(editor->editor,
588 allocation.x + 20, allocation.y + height / 2 + 20,
589 width - 40, height / 2 - 40);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200590}
591
592static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200593text_entry_activate(struct text_entry *entry,
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200594 struct wl_seat *seat)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200595{
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200596 struct wl_surface *surface = window_get_wl_surface(entry->window);
597
Jan Arne Petersen61381972013-01-31 15:52:21 +0100598 if (entry->click_to_show && entry->active) {
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200599 wl_text_input_show_input_panel(entry->text_input);
Jan Arne Petersen61381972013-01-31 15:52:21 +0100600
601 return;
602 }
603
604 if (!entry->click_to_show)
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200605 wl_text_input_show_input_panel(entry->text_input);
Jan Arne Petersen61381972013-01-31 15:52:21 +0100606
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200607 wl_text_input_activate(entry->text_input,
608 seat,
609 surface);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200610}
611
612static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200613text_entry_deactivate(struct text_entry *entry,
614 struct wl_seat *seat)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200615{
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200616 wl_text_input_deactivate(entry->text_input,
617 seat);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200618}
619
620static void
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200621text_entry_update_layout(struct text_entry *entry)
622{
623 char *text;
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100624 PangoAttrList *attr_list;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200625
Jan Arne Petersen68516862013-04-18 16:47:42 +0200626 assert(entry->cursor <= (strlen(entry->text) +
627 (entry->preedit.text ? strlen(entry->preedit.text) : 0)));
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200628
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100629 if (entry->preedit.text) {
630 text = malloc(strlen(entry->text) + strlen(entry->preedit.text) + 1);
631 strncpy(text, entry->text, entry->cursor);
632 strcpy(text + entry->cursor, entry->preedit.text);
633 strcpy(text + entry->cursor + strlen(entry->preedit.text),
634 entry->text + entry->cursor);
635 } else {
636 text = strdup(entry->text);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200637 }
638
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100639 if (entry->cursor != entry->anchor) {
640 int start_index = MIN(entry->cursor, entry->anchor);
641 int end_index = MAX(entry->cursor, entry->anchor);
642 PangoAttribute *attr;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200643
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100644 attr_list = pango_attr_list_copy(entry->preedit.attr_list);
645
646 if (!attr_list)
647 attr_list = pango_attr_list_new();
648
649 attr = pango_attr_background_new(0.3 * 65535, 0.3 * 65535, 65535);
650 attr->start_index = start_index;
651 attr->end_index = end_index;
652 pango_attr_list_insert(attr_list, attr);
653
654 attr = pango_attr_foreground_new(65535, 65535, 65535);
655 attr->start_index = start_index;
656 attr->end_index = end_index;
657 pango_attr_list_insert(attr_list, attr);
658 } else {
659 attr_list = pango_attr_list_ref(entry->preedit.attr_list);
660 }
661
662 if (entry->preedit.text && !entry->preedit.attr_list) {
663 PangoAttribute *attr;
664
665 if (!attr_list)
666 attr_list = pango_attr_list_new();
667
668 attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
669 attr->start_index = entry->cursor;
670 attr->end_index = entry->cursor + strlen(entry->preedit.text);
671 pango_attr_list_insert(attr_list, attr);
672 }
673
674 if (entry->layout) {
675 pango_layout_set_text(entry->layout, text, -1);
676 pango_layout_set_attributes(entry->layout, attr_list);
677 }
678
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200679 free(text);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100680 pango_attr_list_unref(attr_list);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200681}
682
683static void
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100684text_entry_update(struct text_entry *entry)
685{
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200686 struct rectangle cursor_rectangle;
687
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200688 wl_text_input_set_content_type(entry->text_input,
689 WL_TEXT_INPUT_CONTENT_HINT_NONE,
690 entry->content_purpose);
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100691
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200692 wl_text_input_set_surrounding_text(entry->text_input,
693 entry->text,
694 entry->cursor,
695 entry->anchor);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100696
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200697 if (entry->preferred_language)
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200698 wl_text_input_set_preferred_language(entry->text_input,
699 entry->preferred_language);
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200700
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200701 text_entry_get_cursor_rectangle(entry, &cursor_rectangle);
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200702 wl_text_input_set_cursor_rectangle(entry->text_input, cursor_rectangle.x, cursor_rectangle.y,
703 cursor_rectangle.width, cursor_rectangle.height);
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200704
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200705 wl_text_input_commit_state(entry->text_input, ++entry->serial);
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100706}
707
708static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100709text_entry_insert_at_cursor(struct text_entry *entry, const char *text,
710 int32_t cursor, int32_t anchor)
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200711{
712 char *new_text = malloc(strlen(entry->text) + strlen(text) + 1);
713
714 strncpy(new_text, entry->text, entry->cursor);
715 strcpy(new_text + entry->cursor, text);
716 strcpy(new_text + entry->cursor + strlen(text),
717 entry->text + entry->cursor);
718
719 free(entry->text);
720 entry->text = new_text;
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100721 if (anchor >= 0)
722 entry->anchor = entry->cursor + strlen(text) + anchor;
723 else
724 entry->anchor = entry->cursor + 1 + anchor;
Jan Arne Petersen68516862013-04-18 16:47:42 +0200725
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100726 if (cursor >= 0)
727 entry->cursor += strlen(text) + cursor;
728 else
729 entry->cursor += 1 + cursor;
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200730
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200731 text_entry_update_layout(entry);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100732
733 widget_schedule_redraw(entry->widget);
734
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100735 text_entry_update(entry);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200736}
737
738static void
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100739text_entry_reset_preedit(struct text_entry *entry)
740{
741 entry->preedit.cursor = 0;
742
743 free(entry->preedit.text);
744 entry->preedit.text = NULL;
745
746 free(entry->preedit.commit);
747 entry->preedit.commit = NULL;
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100748
749 pango_attr_list_unref(entry->preedit.attr_list);
750 entry->preedit.attr_list = NULL;
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100751}
752
753static void
754text_entry_commit_and_reset(struct text_entry *entry)
755{
756 char *commit = NULL;
757
758 if (entry->preedit.commit)
759 commit = strdup(entry->preedit.commit);
760
761 text_entry_reset_preedit(entry);
762 if (commit) {
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100763 text_entry_insert_at_cursor(entry, commit, 0, 0);
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100764 free(commit);
765 }
Jan Arne Petersen08015b62013-04-18 16:47:18 +0200766
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200767 wl_text_input_reset(entry->text_input);
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200768 text_entry_update(entry);
769 entry->reset_serial = entry->serial;
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100770}
771
772static void
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200773text_entry_set_preedit(struct text_entry *entry,
774 const char *preedit_text,
775 int preedit_cursor)
776{
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100777 text_entry_reset_preedit(entry);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200778
779 if (!preedit_text)
780 return;
781
Jan Arne Petersen46535312013-01-16 21:26:38 +0100782 entry->preedit.text = strdup(preedit_text);
783 entry->preedit.cursor = preedit_cursor;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200784
785 text_entry_update_layout(entry);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100786
787 widget_schedule_redraw(entry->widget);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200788}
789
Jan Arne Petersen3489ba92013-01-16 21:26:47 +0100790static uint32_t
791text_entry_try_invoke_preedit_action(struct text_entry *entry,
792 int32_t x, int32_t y,
793 uint32_t button,
794 enum wl_pointer_button_state state)
795{
796 int index, trailing;
797 uint32_t cursor;
Jan Arne Petersen68516862013-04-18 16:47:42 +0200798 const char *text;
Jan Arne Petersen3489ba92013-01-16 21:26:47 +0100799
800 if (!entry->preedit.text)
801 return 0;
802
803 pango_layout_xy_to_index(entry->layout,
804 x * PANGO_SCALE, y * PANGO_SCALE,
805 &index, &trailing);
Jan Arne Petersen68516862013-04-18 16:47:42 +0200806
807 text = pango_layout_get_text(entry->layout);
808 cursor = g_utf8_offset_to_pointer(text + index, trailing) - text;
Jan Arne Petersen3489ba92013-01-16 21:26:47 +0100809
810 if (cursor < entry->cursor ||
811 cursor > entry->cursor + strlen(entry->preedit.text)) {
812 return 0;
813 }
814
815 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200816 wl_text_input_invoke_action(entry->text_input,
817 button,
818 cursor - entry->cursor);
Jan Arne Petersen3489ba92013-01-16 21:26:47 +0100819
820 return 1;
821}
822
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200823static bool
824text_entry_has_preedit(struct text_entry *entry)
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200825{
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200826 return entry->preedit.text && (strlen(entry->preedit.text) > 0);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200827}
828
829static void
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200830text_entry_set_cursor_position(struct text_entry *entry,
831 int32_t x, int32_t y,
832 bool move_anchor)
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200833{
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100834 int index, trailing;
Jan Arne Petersen68516862013-04-18 16:47:42 +0200835 const char *text;
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200836 uint32_t cursor;
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100837
838 pango_layout_xy_to_index(entry->layout,
839 x * PANGO_SCALE, y * PANGO_SCALE,
840 &index, &trailing);
Jan Arne Petersen68516862013-04-18 16:47:42 +0200841
842 text = pango_layout_get_text(entry->layout);
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200843
844 cursor = g_utf8_offset_to_pointer(text + index, trailing) - text;
845
846 if (move_anchor)
847 entry->anchor = cursor;
848
849 if (text_entry_has_preedit(entry)) {
850 text_entry_commit_and_reset(entry);
851
852 assert(!text_entry_has_preedit(entry));
853 }
854
855 if (entry->cursor == cursor)
856 return;
857
858 entry->cursor = cursor;
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100859
860 text_entry_update_layout(entry);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200861
862 widget_schedule_redraw(entry->widget);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100863
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100864 text_entry_update(entry);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200865}
866
867static void
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200868text_entry_delete_text(struct text_entry *entry,
869 uint32_t index, uint32_t length)
870{
Jan Arne Petersen68516862013-04-18 16:47:42 +0200871 uint32_t l;
872
Jan Arne Petersen895a1282013-05-30 13:57:04 +0200873 assert(index <= strlen(entry->text));
874 assert(index + length <= strlen(entry->text));
875 assert(index + length >= length);
Jan Arne Petersen80ad1a92012-09-17 15:28:10 +0200876
Jan Arne Petersen68516862013-04-18 16:47:42 +0200877 l = strlen(entry->text + index + length);
878 memmove(entry->text + index,
879 entry->text + index + length,
880 l + 1);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200881
Jan Arne Petersen9eaa8e52013-05-30 13:57:03 +0200882 if (entry->cursor > (index + length))
883 entry->cursor -= length;
884 else if (entry->cursor > index)
885 entry->cursor = index;
886
887 entry->anchor = entry->cursor;
888
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200889 text_entry_update_layout(entry);
890
891 widget_schedule_redraw(entry->widget);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100892
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100893 text_entry_update(entry);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200894}
895
896static void
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200897text_entry_delete_selected_text(struct text_entry *entry)
898{
899 uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
900 uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
901
902 if (entry->anchor == entry->cursor)
903 return;
904
905 text_entry_delete_text(entry, start_index, end_index - start_index);
906
907 entry->anchor = entry->cursor;
908}
909
910static void
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200911text_entry_get_cursor_rectangle(struct text_entry *entry, struct rectangle *rectangle)
912{
913 struct rectangle allocation;
914 PangoRectangle extents;
915 PangoRectangle cursor_pos;
916
917 widget_get_allocation(entry->widget, &allocation);
918
919 if (entry->preedit.text && entry->preedit.cursor < 0) {
920 rectangle->x = 0;
921 rectangle->y = 0;
922 rectangle->width = 0;
923 rectangle->height = 0;
924 return;
925 }
926
Jan Arne Petersen68516862013-04-18 16:47:42 +0200927
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200928 pango_layout_get_extents(entry->layout, &extents, NULL);
929 pango_layout_get_cursor_pos(entry->layout,
930 entry->cursor + entry->preedit.cursor,
931 &cursor_pos, NULL);
932
933 rectangle->x = allocation.x + (allocation.height / 2) + PANGO_PIXELS(cursor_pos.x);
934 rectangle->y = allocation.y + 10 + PANGO_PIXELS(cursor_pos.y);
935 rectangle->width = PANGO_PIXELS(cursor_pos.width);
936 rectangle->height = PANGO_PIXELS(cursor_pos.height);
937}
938
939static void
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200940text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr)
941{
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100942 PangoRectangle extents;
943 PangoRectangle cursor_pos;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200944
Jan Arne Petersen46535312013-01-16 21:26:38 +0100945 if (entry->preedit.text && entry->preedit.cursor < 0)
946 return;
947
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100948 pango_layout_get_extents(entry->layout, &extents, NULL);
949 pango_layout_get_cursor_pos(entry->layout,
950 entry->cursor + entry->preedit.cursor,
951 &cursor_pos, NULL);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200952
953 cairo_set_line_width(cr, 1.0);
Peter Maatmanb9a23f42013-07-06 20:55:54 +0200954 cairo_move_to(cr, PANGO_PIXELS(cursor_pos.x), PANGO_PIXELS(cursor_pos.y));
955 cairo_line_to(cr, PANGO_PIXELS(cursor_pos.x), PANGO_PIXELS(cursor_pos.y) + PANGO_PIXELS(cursor_pos.height));
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200956 cairo_stroke(cr);
957}
958
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200959static const int text_offset_left = 10;
960
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200961static void
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200962text_entry_redraw_handler(struct widget *widget, void *data)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200963{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200964 struct text_entry *entry = data;
965 cairo_surface_t *surface;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200966 struct rectangle allocation;
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200967 cairo_t *cr;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200968
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200969 surface = window_get_surface(entry->window);
970 widget_get_allocation(entry->widget, &allocation);
971
972 cr = cairo_create(surface);
973 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
974 cairo_clip(cr);
975
976 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
977
978 cairo_push_group(cr);
979 cairo_translate(cr, allocation.x, allocation.y);
980
981 cairo_set_source_rgba(cr, 1, 1, 1, 1);
982 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
983 cairo_fill(cr);
984
985 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
986
987 if (entry->active) {
988 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
989 cairo_set_line_width (cr, 3);
990 cairo_set_source_rgba(cr, 0, 0, 1, 1.0);
991 cairo_stroke(cr);
992 }
993
994 cairo_set_source_rgba(cr, 0, 0, 0, 1);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200995
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +0200996 cairo_translate(cr, text_offset_left, allocation.height / 2);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200997
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100998 if (!entry->layout)
999 entry->layout = pango_cairo_create_layout(cr);
1000 else
1001 pango_cairo_update_layout(cr, entry->layout);
1002
1003 text_entry_update_layout(entry);
1004
1005 pango_cairo_show_layout(cr, entry->layout);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001006
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001007 text_entry_draw_cursor(entry, cr);
1008
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001009 cairo_pop_group_to_source(cr);
1010 cairo_paint(cr);
1011
1012 cairo_destroy(cr);
1013 cairo_surface_destroy(surface);
1014}
1015
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001016static int
1017text_entry_motion_handler(struct widget *widget,
1018 struct input *input, uint32_t time,
1019 float x, float y, void *data)
1020{
1021 struct text_entry *entry = data;
1022 struct rectangle allocation;
1023
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001024 if (!entry->button_pressed) {
1025 return CURSOR_IBEAM;
1026 }
1027
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001028 widget_get_allocation(entry->widget, &allocation);
1029
1030 text_entry_set_cursor_position(entry,
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +02001031 x - allocation.x - text_offset_left,
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001032 y - allocation.y - text_offset_left,
1033 false);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001034
1035 return CURSOR_IBEAM;
1036}
1037
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001038static void
1039text_entry_button_handler(struct widget *widget,
1040 struct input *input, uint32_t time,
1041 uint32_t button,
1042 enum wl_pointer_button_state state, void *data)
1043{
1044 struct text_entry *entry = data;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001045 struct rectangle allocation;
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001046 struct editor *editor;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001047 int32_t x, y;
Jan Arne Petersen3489ba92013-01-16 21:26:47 +01001048 uint32_t result;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001049
1050 widget_get_allocation(entry->widget, &allocation);
1051 input_get_position(input, &x, &y);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001052
Jan Arne Petersen3489ba92013-01-16 21:26:47 +01001053 x -= allocation.x + text_offset_left;
1054 y -= allocation.y + text_offset_left;
1055
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001056 editor = window_get_user_data(entry->window);
1057
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001058 if (button == BTN_LEFT) {
1059 entry->button_pressed = (state == WL_POINTER_BUTTON_STATE_PRESSED);
Jan Arne Petersen3489ba92013-01-16 21:26:47 +01001060
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001061 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
1062 input_grab(input, entry->widget, button);
1063 else
1064 input_ungrab(input);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001065 }
1066
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001067 if (text_entry_has_preedit(entry)) {
1068 result = text_entry_try_invoke_preedit_action(entry, x, y, button, state);
1069
1070 if (result)
1071 return;
1072 }
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001073
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001074 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
1075 struct wl_seat *seat = input_get_seat(input);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001076
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001077 text_entry_activate(entry, seat);
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001078 editor->active_entry = entry;
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001079
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001080 text_entry_set_cursor_position(entry, x, y, true);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001081 }
1082}
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001083
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001084static void
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -08001085text_entry_touch_handler(struct widget *widget, struct input *input,
1086 uint32_t serial, uint32_t time, int32_t id,
1087 float tx, float ty, void *data)
1088{
1089 struct text_entry *entry = data;
1090 struct wl_seat *seat = input_get_seat(input);
1091 struct rectangle allocation;
1092 struct editor *editor;
1093 int32_t x, y;
1094
1095 widget_get_allocation(entry->widget, &allocation);
1096
1097 x = tx - (allocation.x + text_offset_left);
1098 y = ty - (allocation.y + text_offset_left);
1099
1100 editor = window_get_user_data(entry->window);
1101 text_entry_activate(entry, seat);
1102 editor->active_entry = entry;
1103
1104 text_entry_set_cursor_position(entry, x, y, true);
1105}
1106
1107static void
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001108editor_button_handler(struct widget *widget,
1109 struct input *input, uint32_t time,
1110 uint32_t button,
1111 enum wl_pointer_button_state state, void *data)
1112{
1113 struct editor *editor = data;
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001114
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001115 if (button != BTN_LEFT) {
1116 return;
1117 }
Jan Arne Petersene829adc2012-08-10 16:47:22 +02001118
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001119 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
1120 struct wl_seat *seat = input_get_seat(input);
1121
Jan Arne Petersene829adc2012-08-10 16:47:22 +02001122 text_entry_deactivate(editor->entry, seat);
1123 text_entry_deactivate(editor->editor, seat);
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001124 editor->active_entry = NULL;
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001125 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001126}
1127
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -08001128static void
1129editor_touch_handler(struct widget *widget, struct input *input,
1130 uint32_t serial, uint32_t time, int32_t id,
1131 float tx, float ty, void *data)
1132{
1133 struct editor *editor = data;
1134
1135 struct wl_seat *seat = input_get_seat(input);
1136
1137 text_entry_deactivate(editor->entry, seat);
1138 text_entry_deactivate(editor->editor, seat);
1139 editor->active_entry = NULL;
1140}
Kristian Høgsberg78858902014-01-01 23:57:42 -08001141
1142static void
1143keyboard_focus_handler(struct window *window,
1144 struct input *device, void *data)
1145{
1146 struct editor *editor = data;
1147
1148 window_schedule_redraw(editor->window);
1149}
1150
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001151static void
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001152key_handler(struct window *window,
1153 struct input *input, uint32_t time,
1154 uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
1155 void *data)
1156{
1157 struct editor *editor = data;
1158 struct text_entry *entry;
Jan Arne Petersen68516862013-04-18 16:47:42 +02001159 const char *new_char;
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001160 char text[16];
1161
1162 if (!editor->active_entry)
1163 return;
1164
1165 entry = editor->active_entry;
1166
1167 if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
1168 return;
1169
1170 switch (sym) {
1171 case XKB_KEY_BackSpace:
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +01001172 text_entry_commit_and_reset(entry);
1173
Jan Arne Petersen68516862013-04-18 16:47:42 +02001174 new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
1175 if (new_char != NULL)
1176 text_entry_delete_text(entry,
1177 new_char - entry->text,
1178 (entry->text + entry->cursor) - new_char);
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001179 break;
1180 case XKB_KEY_Delete:
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +01001181 text_entry_commit_and_reset(entry);
1182
Jan Arne Petersen68516862013-04-18 16:47:42 +02001183 new_char = utf8_next_char(entry->text + entry->cursor);
1184 if (new_char != NULL)
1185 text_entry_delete_text(entry,
1186 entry->cursor,
1187 new_char - (entry->text + entry->cursor));
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001188 break;
1189 case XKB_KEY_Left:
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +01001190 text_entry_commit_and_reset(entry);
1191
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001192 new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
1193 if (new_char != NULL) {
1194 entry->cursor = new_char - entry->text;
Rob Bradford70002832013-07-11 16:00:00 +01001195 if (!(input_get_modifiers(input) & MOD_SHIFT_MASK))
1196 entry->anchor = entry->cursor;
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001197 widget_schedule_redraw(entry->widget);
1198 }
1199 break;
1200 case XKB_KEY_Right:
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +01001201 text_entry_commit_and_reset(entry);
1202
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001203 new_char = utf8_next_char(entry->text + entry->cursor);
1204 if (new_char != NULL) {
1205 entry->cursor = new_char - entry->text;
Rob Bradford70002832013-07-11 16:00:00 +01001206 if (!(input_get_modifiers(input) & MOD_SHIFT_MASK))
1207 entry->anchor = entry->cursor;
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001208 widget_schedule_redraw(entry->widget);
1209 }
1210 break;
Peter Maatman08c38d42013-07-06 20:42:59 +02001211 case XKB_KEY_Escape:
1212 break;
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001213 default:
1214 if (xkb_keysym_to_utf8(sym, text, sizeof(text)) <= 0)
1215 break;
1216
Peter Maatman08c38d42013-07-06 20:42:59 +02001217 text_entry_commit_and_reset(entry);
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +01001218
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +01001219 text_entry_insert_at_cursor(entry, text, 0, 0);
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001220 break;
1221 }
1222
1223 widget_schedule_redraw(entry->widget);
1224}
1225
1226static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001227global_handler(struct display *display, uint32_t name,
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001228 const char *interface, uint32_t version, void *data)
1229{
1230 struct editor *editor = data;
1231
Jan Arne Petersen62ece762013-04-18 16:47:36 +02001232 if (!strcmp(interface, "wl_text_input_manager")) {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +02001233 editor->text_input_manager =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001234 display_bind(display, name,
Jan Arne Petersen62ece762013-04-18 16:47:36 +02001235 &wl_text_input_manager_interface, 1);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001236 }
1237}
1238
1239int
1240main(int argc, char *argv[])
1241{
1242 struct editor editor;
Jan Arne Petersen61381972013-01-31 15:52:21 +01001243 int i;
1244 uint32_t click_to_show = 0;
Jan Arne Petersen9d419132013-04-18 16:47:16 +02001245 const char *preferred_language = NULL;
Jan Arne Petersen61381972013-01-31 15:52:21 +01001246
Jan Arne Petersen9d419132013-04-18 16:47:16 +02001247 for (i = 1; i < argc; i++) {
Jan Arne Petersen61381972013-01-31 15:52:21 +01001248 if (strcmp("--click-to-show", argv[i]) == 0)
1249 click_to_show = 1;
Jan Arne Petersen9d419132013-04-18 16:47:16 +02001250 else if (strcmp("--preferred-language", argv[i]) == 0) {
1251 if (i + 1 < argc) {
1252 preferred_language = argv[i + 1];
1253 i++;
1254 }
1255 }
1256 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001257
Jan Arne Petersen25f6db52012-11-05 03:26:40 +01001258 memset(&editor, 0, sizeof editor);
1259
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +01001260#ifdef HAVE_PANGO
1261 g_type_init();
1262#endif
1263
Kristian Høgsberg4172f662013-02-20 15:27:49 -05001264 editor.display = display_create(&argc, argv);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001265 if (editor.display == NULL) {
1266 fprintf(stderr, "failed to create display: %m\n");
1267 return -1;
1268 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001269
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001270 display_set_user_data(editor.display, &editor);
1271 display_set_global_handler(editor.display, global_handler);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001272
1273 editor.window = window_create(editor.display);
Jason Ekstrandee7fefc2013-10-13 19:08:38 -05001274 editor.widget = window_frame_create(editor.window, &editor);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001275
1276 editor.entry = text_entry_create(&editor, "Entry");
Jan Arne Petersen61381972013-01-31 15:52:21 +01001277 editor.entry->click_to_show = click_to_show;
Jan Arne Petersen9d419132013-04-18 16:47:16 +02001278 if (preferred_language)
1279 editor.entry->preferred_language = strdup(preferred_language);
Jan Arne Petersen0558a932013-01-16 21:26:45 +01001280 editor.editor = text_entry_create(&editor, "Numeric");
Jan Arne Petersen62ece762013-04-18 16:47:36 +02001281 editor.editor->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
Jan Arne Petersen61381972013-01-31 15:52:21 +01001282 editor.editor->click_to_show = click_to_show;
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001283
1284 window_set_title(editor.window, "Text Editor");
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001285 window_set_key_handler(editor.window, key_handler);
Kristian Høgsberg78858902014-01-01 23:57:42 -08001286 window_set_keyboard_focus_handler(editor.window,
1287 keyboard_focus_handler);
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001288 window_set_user_data(editor.window, &editor);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001289
1290 widget_set_redraw_handler(editor.widget, redraw_handler);
1291 widget_set_resize_handler(editor.widget, resize_handler);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001292 widget_set_button_handler(editor.widget, editor_button_handler);
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -08001293 widget_set_touch_down_handler(editor.widget, editor_touch_handler);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001294
1295 window_schedule_resize(editor.window, 500, 400);
1296
1297 display_run(editor.display);
1298
1299 text_entry_destroy(editor.entry);
1300 text_entry_destroy(editor.editor);
1301
1302 return 0;
1303}