blob: 9299a0507110fbbb318b06a416b2e230bd884670 [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
Manuel Bachmann8986c182014-04-18 12:50:14 +0200113static void
114move_up(const char *p, uint32_t *cursor)
115{
116 const char *posr, *posr_i;
117 char text[16];
118
119 xkb_keysym_to_utf8(XKB_KEY_Return, text, sizeof(text));
120
121 posr = strstr(p, text);
122 while (posr) {
123 if (*cursor > (unsigned)(posr-p)) {
124 posr_i = strstr(posr+1, text);
125 if (!posr_i || !(*cursor > (unsigned)(posr_i-p))) {
126 *cursor = posr-p;
127 break;
128 }
129 posr = posr_i;
130 } else {
131 break;
132 }
133 }
134}
135
136static void
137move_down(const char *p, uint32_t *cursor)
138{
139 const char *posr;
140 char text[16];
141
142 xkb_keysym_to_utf8(XKB_KEY_Return, text, sizeof(text));
143
144 posr = strstr(p, text);
145 while (posr) {
146 if (*cursor <= (unsigned)(posr-p)) {
147 *cursor = posr-p + 1;
148 break;
149 }
150 posr = strstr(posr+1, text);
151 }
152}
153
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200154static void text_entry_redraw_handler(struct widget *widget, void *data);
155static void text_entry_button_handler(struct widget *widget,
156 struct input *input, uint32_t time,
157 uint32_t button,
158 enum wl_pointer_button_state state, void *data);
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -0800159static void text_entry_touch_handler(struct widget *widget, struct input *input,
160 uint32_t serial, uint32_t time, int32_t id,
161 float tx, float ty, void *data);
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200162static int text_entry_motion_handler(struct widget *widget,
163 struct input *input, uint32_t time,
164 float x, float y, void *data);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100165static void text_entry_insert_at_cursor(struct text_entry *entry, const char *text,
166 int32_t cursor, int32_t anchor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200167static void text_entry_set_preedit(struct text_entry *entry,
168 const char *preedit_text,
169 int preedit_cursor);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200170static void text_entry_delete_text(struct text_entry *entry,
171 uint32_t index, uint32_t length);
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200172static void text_entry_delete_selected_text(struct text_entry *entry);
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100173static void text_entry_reset_preedit(struct text_entry *entry);
174static void text_entry_commit_and_reset(struct text_entry *entry);
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200175static void text_entry_get_cursor_rectangle(struct text_entry *entry, struct rectangle *rectangle);
176static void text_entry_update(struct text_entry *entry);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200177
178static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200179text_input_commit_string(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200180 struct wl_text_input *text_input,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100181 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100182 const char *text)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200183{
184 struct text_entry *entry = data;
185
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200186 if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) {
187 fprintf(stderr, "Ignore commit. Serial: %u, Current: %u, Reset: %u\n",
188 serial, entry->serial, entry->reset_serial);
189 return;
190 }
191
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200192 if (entry->pending_commit.invalid_delete) {
193 fprintf(stderr, "Ignore commit. Invalid previous delete_surrounding event.\n");
194 memset(&entry->pending_commit, 0, sizeof entry->pending_commit);
195 return;
196 }
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100197
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200198 text_entry_reset_preedit(entry);
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200199
200 if (entry->pending_commit.delete_length) {
201 text_entry_delete_text(entry,
202 entry->pending_commit.delete_index,
203 entry->pending_commit.delete_length);
Jan Arne Petersena96953d2013-05-30 13:57:02 +0200204 } else {
205 text_entry_delete_selected_text(entry);
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200206 }
207
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100208 text_entry_insert_at_cursor(entry, text,
209 entry->pending_commit.cursor,
210 entry->pending_commit.anchor);
211
212 memset(&entry->pending_commit, 0, sizeof entry->pending_commit);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200213
214 widget_schedule_redraw(entry->widget);
215}
216
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200217static void
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200218clear_pending_preedit(struct text_entry *entry)
219{
220 memset(&entry->pending_commit, 0, sizeof entry->pending_commit);
221
222 pango_attr_list_unref(entry->preedit_info.attr_list);
223
224 entry->preedit_info.cursor = 0;
225 entry->preedit_info.attr_list = NULL;
226
227 memset(&entry->preedit_info, 0, sizeof entry->preedit_info);
228}
229
230static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200231text_input_preedit_string(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200232 struct wl_text_input *text_input,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100233 uint32_t serial,
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200234 const char *text,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100235 const char *commit)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200236{
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200237 struct text_entry *entry = data;
238
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200239 if ((entry->serial - serial) > (entry->serial - entry->reset_serial)) {
240 fprintf(stderr, "Ignore preedit_string. Serial: %u, Current: %u, Reset: %u\n",
241 serial, entry->serial, entry->reset_serial);
242 clear_pending_preedit(entry);
243 return;
244 }
245
246 if (entry->pending_commit.invalid_delete) {
247 fprintf(stderr, "Ignore preedit_string. Invalid previous delete_surrounding event.\n");
248 clear_pending_preedit(entry);
249 return;
250 }
251
Jan Arne Petersena96953d2013-05-30 13:57:02 +0200252 if (entry->pending_commit.delete_length) {
253 text_entry_delete_text(entry,
254 entry->pending_commit.delete_index,
255 entry->pending_commit.delete_length);
256 } else {
257 text_entry_delete_selected_text(entry);
258 }
Jan Arne Petersena96953d2013-05-30 13:57:02 +0200259
Jan Arne Petersen46535312013-01-16 21:26:38 +0100260 text_entry_set_preedit(entry, text, entry->preedit_info.cursor);
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100261 entry->preedit.commit = strdup(commit);
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200262 entry->preedit.attr_list = pango_attr_list_ref(entry->preedit_info.attr_list);
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100263
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200264 clear_pending_preedit(entry);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200265
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200266 text_entry_update(entry);
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200267
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200268 widget_schedule_redraw(entry->widget);
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200269}
270
271static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200272text_input_delete_surrounding_text(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200273 struct wl_text_input *text_input,
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200274 int32_t index,
275 uint32_t length)
276{
277 struct text_entry *entry = data;
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200278 uint32_t text_length;
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200279
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200280 entry->pending_commit.delete_index = entry->cursor + index;
281 entry->pending_commit.delete_length = length;
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200282 entry->pending_commit.invalid_delete = false;
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200283
Jan Arne Petersen68516862013-04-18 16:47:42 +0200284 text_length = strlen(entry->text);
Jan Arne Petersen919bc142013-04-18 16:47:34 +0200285
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200286 if (entry->pending_commit.delete_index > text_length ||
287 length > text_length ||
Jan Arne Petersen895a1282013-05-30 13:57:04 +0200288 entry->pending_commit.delete_index + length > text_length) {
Jan Arne Petersen8ccb7cc2013-05-30 13:57:05 +0200289 fprintf(stderr, "delete_surrounding_text: Invalid index: %d," \
290 "length %u'; cursor: %u text length: %u\n", index, length, entry->cursor, text_length);
291 entry->pending_commit.invalid_delete = true;
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200292 return;
293 }
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200294}
295
296static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200297text_input_cursor_position(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200298 struct wl_text_input *text_input,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100299 int32_t index,
300 int32_t anchor)
301{
302 struct text_entry *entry = data;
303
304 entry->pending_commit.cursor = index;
305 entry->pending_commit.anchor = anchor;
306}
307
308static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200309text_input_preedit_styling(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200310 struct wl_text_input *text_input,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100311 uint32_t index,
312 uint32_t length,
313 uint32_t style)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200314{
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100315 struct text_entry *entry = data;
316 PangoAttribute *attr1 = NULL;
317 PangoAttribute *attr2 = NULL;
318
319 if (!entry->preedit_info.attr_list)
320 entry->preedit_info.attr_list = pango_attr_list_new();
321
322 switch (style) {
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200323 case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
324 case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100325 attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
326 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200327 case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT:
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100328 attr1 = pango_attr_underline_new(PANGO_UNDERLINE_ERROR);
329 attr2 = pango_attr_underline_color_new(65535, 0, 0);
330 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200331 case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION:
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100332 attr1 = pango_attr_background_new(0.3 * 65535, 0.3 * 65535, 65535);
333 attr2 = pango_attr_foreground_new(65535, 65535, 65535);
334 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200335 case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
336 case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE:
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100337 attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
338 attr2 = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
339 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200340 case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE:
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100341 attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
342 attr2 = pango_attr_foreground_new(0.3 * 65535, 0.3 * 65535, 0.3 * 65535);
343 break;
344 }
345
346 if (attr1) {
347 attr1->start_index = entry->cursor + index;
348 attr1->end_index = entry->cursor + index + length;
349 pango_attr_list_insert(entry->preedit_info.attr_list, attr1);
350 }
351
352 if (attr2) {
353 attr2->start_index = entry->cursor + index;
354 attr2->end_index = entry->cursor + index + length;
355 pango_attr_list_insert(entry->preedit_info.attr_list, attr2);
356 }
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200357}
358
359static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200360text_input_preedit_cursor(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200361 struct wl_text_input *text_input,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100362 int32_t index)
363{
364 struct text_entry *entry = data;
365
366 entry->preedit_info.cursor = index;
367}
368
369static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200370text_input_modifiers_map(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200371 struct wl_text_input *text_input,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100372 struct wl_array *map)
373{
Jan Arne Petersencd997062012-11-18 19:06:44 +0100374 struct text_entry *entry = data;
375
376 entry->keysym.shift_mask = keysym_modifiers_get_mask(map, "Shift");
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100377}
378
379static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200380text_input_keysym(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200381 struct wl_text_input *text_input,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100382 uint32_t serial,
383 uint32_t time,
384 uint32_t key,
385 uint32_t state,
386 uint32_t modifiers)
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200387{
Jan Arne Petersen8aba11d2012-09-17 15:28:07 +0200388 struct text_entry *entry = data;
Jan Arne Petersen6345faa2012-11-05 03:26:39 +0100389 const char *new_char;
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200390
Jan Arne Petersencd997062012-11-18 19:06:44 +0100391 if (key == XKB_KEY_Left ||
392 key == XKB_KEY_Right) {
393 if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
394 return;
395
396 if (key == XKB_KEY_Left)
397 new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
398 else
399 new_char = utf8_next_char(entry->text + entry->cursor);
400
401 if (new_char != NULL) {
402 entry->cursor = new_char - entry->text;
Jan Arne Petersencd997062012-11-18 19:06:44 +0100403 }
404
Jan Arne Petersen68516862013-04-18 16:47:42 +0200405 if (!(modifiers & entry->keysym.shift_mask))
406 entry->anchor = entry->cursor;
407 widget_schedule_redraw(entry->widget);
408
Jan Arne Petersencd997062012-11-18 19:06:44 +0100409 return;
410 }
411
Manuel Bachmann8986c182014-04-18 12:50:14 +0200412 if (key == XKB_KEY_Up ||
413 key == XKB_KEY_Down) {
414 if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
415 return;
416
417 if (key == XKB_KEY_Up)
418 move_up(entry->text, &entry->cursor);
419 else
420 move_down(entry->text, &entry->cursor);
421
422 if (!(modifiers & entry->keysym.shift_mask))
423 entry->anchor = entry->cursor;
424 widget_schedule_redraw(entry->widget);
425
426 return;
427 }
428
Jan Arne Petersen3fb6e712013-01-16 21:26:52 +0100429 if (key == XKB_KEY_BackSpace) {
430 const char *start, *end;
431
Jan Arne Petersendfd34462013-04-18 16:47:26 +0200432 if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
433 return;
434
Jan Arne Petersen3fb6e712013-01-16 21:26:52 +0100435 text_entry_commit_and_reset(entry);
436
437 start = utf8_prev_char(entry->text, entry->text + entry->cursor);
Jan Arne Petersen3fb6e712013-01-16 21:26:52 +0100438 if (start == NULL)
439 return;
440
Daiki Uenob08b3292013-06-28 18:59:44 +0900441 end = utf8_next_char(start);
442
Jan Arne Petersen3fb6e712013-01-16 21:26:52 +0100443 text_entry_delete_text(entry,
444 start - entry->text,
445 end - start);
446
447 return;
448 }
449
Manuel Bachmann8986c182014-04-18 12:50:14 +0200450 if (key == XKB_KEY_Tab ||
451 key == XKB_KEY_KP_Enter ||
452 key == XKB_KEY_Return) {
453 char text[16];
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200454
Manuel Bachmann8986c182014-04-18 12:50:14 +0200455 if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
456 return;
457
458 xkb_keysym_to_utf8(key, text, sizeof(text));
459
460 text_entry_insert_at_cursor(entry, text, 0, 0);
461
462 return;
463 }
Jan Arne Petersen72f60822012-08-10 16:47:19 +0200464}
465
466static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200467text_input_enter(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200468 struct wl_text_input *text_input,
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200469 struct wl_surface *surface)
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200470{
471 struct text_entry *entry = data;
472
Jan Arne Petersen680275f2012-09-24 14:51:14 +0200473 if (surface != window_get_wl_surface(entry->window))
474 return;
475
Derek Foreman237a6842014-12-17 09:43:58 -0600476 entry->active++;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200477
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200478 text_entry_update(entry);
479 entry->reset_serial = entry->serial;
480
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200481 widget_schedule_redraw(entry->widget);
482}
483
484static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200485text_input_leave(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200486 struct wl_text_input *text_input)
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200487{
488 struct text_entry *entry = data;
489
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100490 text_entry_commit_and_reset(entry);
Derek Foreman237a6842014-12-17 09:43:58 -0600491 entry->active--;
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100492
Derek Foreman237a6842014-12-17 09:43:58 -0600493 if (!entry->active)
494 wl_text_input_hide_input_panel(text_input);
Jan Arne Petersen61381972013-01-31 15:52:21 +0100495
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200496 widget_schedule_redraw(entry->widget);
497}
498
Jan Arne Petersen61381972013-01-31 15:52:21 +0100499static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200500text_input_input_panel_state(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200501 struct wl_text_input *text_input,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100502 uint32_t state)
503{
504}
505
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200506static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200507text_input_language(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200508 struct wl_text_input *text_input,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200509 uint32_t serial,
510 const char *language)
511{
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200512 fprintf(stderr, "input language is %s \n", language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200513}
514
515static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200516text_input_text_direction(void *data,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200517 struct wl_text_input *text_input,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200518 uint32_t serial,
519 uint32_t direction)
520{
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200521 struct text_entry *entry = data;
522 PangoContext *context = pango_layout_get_context(entry->layout);
523 PangoDirection pango_direction;
524
525
526 switch (direction) {
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200527 case WL_TEXT_INPUT_TEXT_DIRECTION_LTR:
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200528 pango_direction = PANGO_DIRECTION_LTR;
529 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200530 case WL_TEXT_INPUT_TEXT_DIRECTION_RTL:
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200531 pango_direction = PANGO_DIRECTION_RTL;
532 break;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200533 case WL_TEXT_INPUT_TEXT_DIRECTION_AUTO:
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200534 default:
535 pango_direction = PANGO_DIRECTION_NEUTRAL;
536 }
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200537
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200538 pango_context_set_base_dir(context, pango_direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200539}
540
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200541static const struct wl_text_input_listener text_input_listener = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200542 text_input_enter,
543 text_input_leave,
544 text_input_modifiers_map,
545 text_input_input_panel_state,
546 text_input_preedit_string,
547 text_input_preedit_styling,
548 text_input_preedit_cursor,
549 text_input_commit_string,
550 text_input_cursor_position,
551 text_input_delete_surrounding_text,
552 text_input_keysym,
553 text_input_language,
554 text_input_text_direction
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200555};
556
557static struct text_entry*
558text_entry_create(struct editor *editor, const char *text)
559{
560 struct text_entry *entry;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200561
Brian Lovinbc919262013-08-07 15:34:59 -0700562 entry = xmalloc(sizeof *entry);
563 memset(entry, 0, sizeof *entry);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200564
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200565 entry->widget = widget_add_widget(editor->widget, entry);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200566 entry->window = editor->window;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200567 entry->text = strdup(text);
568 entry->active = 0;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200569 entry->cursor = strlen(text);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200570 entry->anchor = entry->cursor;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200571 entry->text_input = wl_text_input_manager_create_text_input(editor->text_input_manager);
572 wl_text_input_add_listener(entry->text_input, &text_input_listener, entry);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200573
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200574 widget_set_redraw_handler(entry->widget, text_entry_redraw_handler);
575 widget_set_button_handler(entry->widget, text_entry_button_handler);
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200576 widget_set_motion_handler(entry->widget, text_entry_motion_handler);
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -0800577 widget_set_touch_down_handler(entry->widget, text_entry_touch_handler);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200578
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200579 return entry;
580}
581
582static void
583text_entry_destroy(struct text_entry *entry)
584{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200585 widget_destroy(entry->widget);
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200586 wl_text_input_destroy(entry->text_input);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100587 g_clear_object(&entry->layout);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200588 free(entry->text);
589 free(entry);
590}
591
592static void
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200593redraw_handler(struct widget *widget, void *data)
594{
595 struct editor *editor = data;
596 cairo_surface_t *surface;
597 struct rectangle allocation;
598 cairo_t *cr;
599
600 surface = window_get_surface(editor->window);
601 widget_get_allocation(editor->widget, &allocation);
602
603 cr = cairo_create(surface);
604 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
605 cairo_clip(cr);
606
607 cairo_translate(cr, allocation.x, allocation.y);
608
609 /* Draw background */
610 cairo_push_group(cr);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200611 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200612 cairo_set_source_rgba(cr, 1, 1, 1, 1);
613 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
614 cairo_fill(cr);
615
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200616 cairo_pop_group_to_source(cr);
617 cairo_paint(cr);
618
619 cairo_destroy(cr);
620 cairo_surface_destroy(surface);
621}
622
623static void
624text_entry_allocate(struct text_entry *entry, int32_t x, int32_t y,
625 int32_t width, int32_t height)
626{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200627 widget_set_allocation(entry->widget, x, y, width, height);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200628}
629
630static void
631resize_handler(struct widget *widget,
632 int32_t width, int32_t height, void *data)
633{
634 struct editor *editor = data;
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200635 struct rectangle allocation;
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200636
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200637 widget_get_allocation(editor->widget, &allocation);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200638
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200639 text_entry_allocate(editor->entry,
640 allocation.x + 20, allocation.y + 20,
641 width - 40, height / 2 - 40);
642 text_entry_allocate(editor->editor,
643 allocation.x + 20, allocation.y + height / 2 + 20,
644 width - 40, height / 2 - 40);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200645}
646
647static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200648text_entry_activate(struct text_entry *entry,
Jan Arne Petersenf80bc062012-09-09 23:08:34 +0200649 struct wl_seat *seat)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200650{
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200651 struct wl_surface *surface = window_get_wl_surface(entry->window);
652
Jan Arne Petersen61381972013-01-31 15:52:21 +0100653 if (entry->click_to_show && entry->active) {
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200654 wl_text_input_show_input_panel(entry->text_input);
Jan Arne Petersen61381972013-01-31 15:52:21 +0100655
656 return;
657 }
658
659 if (!entry->click_to_show)
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200660 wl_text_input_show_input_panel(entry->text_input);
Jan Arne Petersen61381972013-01-31 15:52:21 +0100661
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200662 wl_text_input_activate(entry->text_input,
663 seat,
664 surface);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200665}
666
667static void
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200668text_entry_deactivate(struct text_entry *entry,
669 struct wl_seat *seat)
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200670{
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200671 wl_text_input_deactivate(entry->text_input,
672 seat);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200673}
674
675static void
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200676text_entry_update_layout(struct text_entry *entry)
677{
678 char *text;
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100679 PangoAttrList *attr_list;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200680
Jan Arne Petersen68516862013-04-18 16:47:42 +0200681 assert(entry->cursor <= (strlen(entry->text) +
682 (entry->preedit.text ? strlen(entry->preedit.text) : 0)));
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200683
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100684 if (entry->preedit.text) {
Derek Foreman22044922014-11-20 15:42:35 -0600685 text = xmalloc(strlen(entry->text) + strlen(entry->preedit.text) + 1);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100686 strncpy(text, entry->text, entry->cursor);
687 strcpy(text + entry->cursor, entry->preedit.text);
688 strcpy(text + entry->cursor + strlen(entry->preedit.text),
689 entry->text + entry->cursor);
690 } else {
691 text = strdup(entry->text);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200692 }
693
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100694 if (entry->cursor != entry->anchor) {
695 int start_index = MIN(entry->cursor, entry->anchor);
696 int end_index = MAX(entry->cursor, entry->anchor);
697 PangoAttribute *attr;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200698
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100699 attr_list = pango_attr_list_copy(entry->preedit.attr_list);
700
701 if (!attr_list)
702 attr_list = pango_attr_list_new();
703
704 attr = pango_attr_background_new(0.3 * 65535, 0.3 * 65535, 65535);
705 attr->start_index = start_index;
706 attr->end_index = end_index;
707 pango_attr_list_insert(attr_list, attr);
708
709 attr = pango_attr_foreground_new(65535, 65535, 65535);
710 attr->start_index = start_index;
711 attr->end_index = end_index;
712 pango_attr_list_insert(attr_list, attr);
713 } else {
714 attr_list = pango_attr_list_ref(entry->preedit.attr_list);
715 }
716
717 if (entry->preedit.text && !entry->preedit.attr_list) {
718 PangoAttribute *attr;
719
720 if (!attr_list)
721 attr_list = pango_attr_list_new();
722
723 attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
724 attr->start_index = entry->cursor;
725 attr->end_index = entry->cursor + strlen(entry->preedit.text);
726 pango_attr_list_insert(attr_list, attr);
727 }
728
729 if (entry->layout) {
730 pango_layout_set_text(entry->layout, text, -1);
731 pango_layout_set_attributes(entry->layout, attr_list);
732 }
733
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200734 free(text);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100735 pango_attr_list_unref(attr_list);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200736}
737
738static void
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100739text_entry_update(struct text_entry *entry)
740{
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200741 struct rectangle cursor_rectangle;
742
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200743 wl_text_input_set_content_type(entry->text_input,
744 WL_TEXT_INPUT_CONTENT_HINT_NONE,
745 entry->content_purpose);
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100746
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200747 wl_text_input_set_surrounding_text(entry->text_input,
748 entry->text,
749 entry->cursor,
750 entry->anchor);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100751
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200752 if (entry->preferred_language)
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200753 wl_text_input_set_preferred_language(entry->text_input,
754 entry->preferred_language);
Jan Arne Petersen9d419132013-04-18 16:47:16 +0200755
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200756 text_entry_get_cursor_rectangle(entry, &cursor_rectangle);
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200757 wl_text_input_set_cursor_rectangle(entry->text_input, cursor_rectangle.x, cursor_rectangle.y,
758 cursor_rectangle.width, cursor_rectangle.height);
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200759
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200760 wl_text_input_commit_state(entry->text_input, ++entry->serial);
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100761}
762
763static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100764text_entry_insert_at_cursor(struct text_entry *entry, const char *text,
765 int32_t cursor, int32_t anchor)
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200766{
Derek Foreman22044922014-11-20 15:42:35 -0600767 char *new_text = xmalloc(strlen(entry->text) + strlen(text) + 1);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200768
769 strncpy(new_text, entry->text, entry->cursor);
770 strcpy(new_text + entry->cursor, text);
771 strcpy(new_text + entry->cursor + strlen(text),
772 entry->text + entry->cursor);
773
774 free(entry->text);
775 entry->text = new_text;
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100776 if (anchor >= 0)
777 entry->anchor = entry->cursor + strlen(text) + anchor;
778 else
779 entry->anchor = entry->cursor + 1 + anchor;
Jan Arne Petersen68516862013-04-18 16:47:42 +0200780
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100781 if (cursor >= 0)
782 entry->cursor += strlen(text) + cursor;
783 else
784 entry->cursor += 1 + cursor;
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200785
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200786 text_entry_update_layout(entry);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100787
788 widget_schedule_redraw(entry->widget);
789
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100790 text_entry_update(entry);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200791}
792
793static void
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100794text_entry_reset_preedit(struct text_entry *entry)
795{
796 entry->preedit.cursor = 0;
797
798 free(entry->preedit.text);
799 entry->preedit.text = NULL;
800
801 free(entry->preedit.commit);
802 entry->preedit.commit = NULL;
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100803
804 pango_attr_list_unref(entry->preedit.attr_list);
805 entry->preedit.attr_list = NULL;
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100806}
807
808static void
809text_entry_commit_and_reset(struct text_entry *entry)
810{
811 char *commit = NULL;
812
813 if (entry->preedit.commit)
814 commit = strdup(entry->preedit.commit);
815
816 text_entry_reset_preedit(entry);
817 if (commit) {
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100818 text_entry_insert_at_cursor(entry, commit, 0, 0);
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100819 free(commit);
820 }
Jan Arne Petersen08015b62013-04-18 16:47:18 +0200821
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200822 wl_text_input_reset(entry->text_input);
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200823 text_entry_update(entry);
824 entry->reset_serial = entry->serial;
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100825}
826
827static void
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200828text_entry_set_preedit(struct text_entry *entry,
829 const char *preedit_text,
830 int preedit_cursor)
831{
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +0100832 text_entry_reset_preedit(entry);
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200833
834 if (!preedit_text)
835 return;
836
Jan Arne Petersen46535312013-01-16 21:26:38 +0100837 entry->preedit.text = strdup(preedit_text);
838 entry->preedit.cursor = preedit_cursor;
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +0200839
840 text_entry_update_layout(entry);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100841
842 widget_schedule_redraw(entry->widget);
Jan Arne Petersen09e7c962012-09-09 23:08:37 +0200843}
844
Jan Arne Petersen3489ba92013-01-16 21:26:47 +0100845static uint32_t
846text_entry_try_invoke_preedit_action(struct text_entry *entry,
847 int32_t x, int32_t y,
848 uint32_t button,
849 enum wl_pointer_button_state state)
850{
851 int index, trailing;
852 uint32_t cursor;
Jan Arne Petersen68516862013-04-18 16:47:42 +0200853 const char *text;
Jan Arne Petersen3489ba92013-01-16 21:26:47 +0100854
855 if (!entry->preedit.text)
856 return 0;
857
858 pango_layout_xy_to_index(entry->layout,
859 x * PANGO_SCALE, y * PANGO_SCALE,
860 &index, &trailing);
Jan Arne Petersen68516862013-04-18 16:47:42 +0200861
862 text = pango_layout_get_text(entry->layout);
863 cursor = g_utf8_offset_to_pointer(text + index, trailing) - text;
Jan Arne Petersen3489ba92013-01-16 21:26:47 +0100864
865 if (cursor < entry->cursor ||
866 cursor > entry->cursor + strlen(entry->preedit.text)) {
867 return 0;
868 }
869
870 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200871 wl_text_input_invoke_action(entry->text_input,
872 button,
873 cursor - entry->cursor);
Jan Arne Petersen3489ba92013-01-16 21:26:47 +0100874
875 return 1;
876}
877
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200878static bool
879text_entry_has_preedit(struct text_entry *entry)
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200880{
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200881 return entry->preedit.text && (strlen(entry->preedit.text) > 0);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200882}
883
884static void
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200885text_entry_set_cursor_position(struct text_entry *entry,
886 int32_t x, int32_t y,
887 bool move_anchor)
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200888{
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100889 int index, trailing;
Jan Arne Petersen68516862013-04-18 16:47:42 +0200890 const char *text;
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200891 uint32_t cursor;
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100892
893 pango_layout_xy_to_index(entry->layout,
894 x * PANGO_SCALE, y * PANGO_SCALE,
895 &index, &trailing);
Jan Arne Petersen68516862013-04-18 16:47:42 +0200896
897 text = pango_layout_get_text(entry->layout);
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +0200898
899 cursor = g_utf8_offset_to_pointer(text + index, trailing) - text;
900
901 if (move_anchor)
902 entry->anchor = cursor;
903
904 if (text_entry_has_preedit(entry)) {
905 text_entry_commit_and_reset(entry);
906
907 assert(!text_entry_has_preedit(entry));
908 }
909
910 if (entry->cursor == cursor)
911 return;
912
913 entry->cursor = cursor;
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100914
915 text_entry_update_layout(entry);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200916
917 widget_schedule_redraw(entry->widget);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100918
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100919 text_entry_update(entry);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +0200920}
921
922static void
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200923text_entry_delete_text(struct text_entry *entry,
924 uint32_t index, uint32_t length)
925{
Jan Arne Petersen68516862013-04-18 16:47:42 +0200926 uint32_t l;
927
Jan Arne Petersen895a1282013-05-30 13:57:04 +0200928 assert(index <= strlen(entry->text));
929 assert(index + length <= strlen(entry->text));
930 assert(index + length >= length);
Jan Arne Petersen80ad1a92012-09-17 15:28:10 +0200931
Jan Arne Petersen68516862013-04-18 16:47:42 +0200932 l = strlen(entry->text + index + length);
933 memmove(entry->text + index,
934 entry->text + index + length,
935 l + 1);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200936
Jan Arne Petersen9eaa8e52013-05-30 13:57:03 +0200937 if (entry->cursor > (index + length))
938 entry->cursor -= length;
939 else if (entry->cursor > index)
940 entry->cursor = index;
941
942 entry->anchor = entry->cursor;
943
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200944 text_entry_update_layout(entry);
945
946 widget_schedule_redraw(entry->widget);
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100947
Jan Arne Petersen0558a932013-01-16 21:26:45 +0100948 text_entry_update(entry);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200949}
950
951static void
Jan Arne Petersene386dd22012-09-17 15:28:09 +0200952text_entry_delete_selected_text(struct text_entry *entry)
953{
954 uint32_t start_index = entry->anchor < entry->cursor ? entry->anchor : entry->cursor;
955 uint32_t end_index = entry->anchor < entry->cursor ? entry->cursor : entry->anchor;
956
957 if (entry->anchor == entry->cursor)
958 return;
959
960 text_entry_delete_text(entry, start_index, end_index - start_index);
961
962 entry->anchor = entry->cursor;
963}
964
965static void
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200966text_entry_get_cursor_rectangle(struct text_entry *entry, struct rectangle *rectangle)
967{
968 struct rectangle allocation;
969 PangoRectangle extents;
970 PangoRectangle cursor_pos;
971
972 widget_get_allocation(entry->widget, &allocation);
973
974 if (entry->preedit.text && entry->preedit.cursor < 0) {
975 rectangle->x = 0;
976 rectangle->y = 0;
977 rectangle->width = 0;
978 rectangle->height = 0;
979 return;
980 }
981
Jan Arne Petersen68516862013-04-18 16:47:42 +0200982
Jan Arne Petersenfe89e712013-04-18 16:47:27 +0200983 pango_layout_get_extents(entry->layout, &extents, NULL);
984 pango_layout_get_cursor_pos(entry->layout,
985 entry->cursor + entry->preedit.cursor,
986 &cursor_pos, NULL);
987
988 rectangle->x = allocation.x + (allocation.height / 2) + PANGO_PIXELS(cursor_pos.x);
989 rectangle->y = allocation.y + 10 + PANGO_PIXELS(cursor_pos.y);
990 rectangle->width = PANGO_PIXELS(cursor_pos.width);
991 rectangle->height = PANGO_PIXELS(cursor_pos.height);
992}
993
994static void
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200995text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr)
996{
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +0100997 PangoRectangle extents;
998 PangoRectangle cursor_pos;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +0200999
Jan Arne Petersen46535312013-01-16 21:26:38 +01001000 if (entry->preedit.text && entry->preedit.cursor < 0)
1001 return;
1002
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +01001003 pango_layout_get_extents(entry->layout, &extents, NULL);
1004 pango_layout_get_cursor_pos(entry->layout,
1005 entry->cursor + entry->preedit.cursor,
1006 &cursor_pos, NULL);
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001007
1008 cairo_set_line_width(cr, 1.0);
Peter Maatmanb9a23f42013-07-06 20:55:54 +02001009 cairo_move_to(cr, PANGO_PIXELS(cursor_pos.x), PANGO_PIXELS(cursor_pos.y));
1010 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 +02001011 cairo_stroke(cr);
1012}
1013
Ander Conselvan de Oliveira8e37d962014-05-08 14:55:50 +03001014static int
1015text_offset_left(struct rectangle *allocation)
1016{
1017 return 10;
1018}
1019
1020static int
1021text_offset_top(struct rectangle *allocation)
1022{
1023 return allocation->height / 2;
1024}
Philipp Brüschweiler9f897c72012-10-02 11:06:53 +02001025
Jan Arne Petersenc1fbcb72012-09-09 23:08:39 +02001026static void
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001027text_entry_redraw_handler(struct widget *widget, void *data)
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001028{
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001029 struct text_entry *entry = data;
1030 cairo_surface_t *surface;
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001031 struct rectangle allocation;
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001032 cairo_t *cr;
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001033
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001034 surface = window_get_surface(entry->window);
1035 widget_get_allocation(entry->widget, &allocation);
1036
1037 cr = cairo_create(surface);
1038 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
1039 cairo_clip(cr);
1040
1041 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1042
1043 cairo_push_group(cr);
1044 cairo_translate(cr, allocation.x, allocation.y);
1045
1046 cairo_set_source_rgba(cr, 1, 1, 1, 1);
1047 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
1048 cairo_fill(cr);
1049
1050 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1051
1052 if (entry->active) {
1053 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
1054 cairo_set_line_width (cr, 3);
1055 cairo_set_source_rgba(cr, 0, 0, 1, 1.0);
1056 cairo_stroke(cr);
1057 }
1058
1059 cairo_set_source_rgba(cr, 0, 0, 0, 1);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001060
Ander Conselvan de Oliveira8e37d962014-05-08 14:55:50 +03001061 cairo_translate(cr,
1062 text_offset_left(&allocation),
1063 text_offset_top(&allocation));
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001064
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +01001065 if (!entry->layout)
1066 entry->layout = pango_cairo_create_layout(cr);
1067 else
1068 pango_cairo_update_layout(cr, entry->layout);
1069
1070 text_entry_update_layout(entry);
1071
1072 pango_cairo_show_layout(cr, entry->layout);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001073
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001074 text_entry_draw_cursor(entry, cr);
1075
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001076 cairo_pop_group_to_source(cr);
1077 cairo_paint(cr);
1078
1079 cairo_destroy(cr);
1080 cairo_surface_destroy(surface);
1081}
1082
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001083static int
1084text_entry_motion_handler(struct widget *widget,
1085 struct input *input, uint32_t time,
1086 float x, float y, void *data)
1087{
1088 struct text_entry *entry = data;
1089 struct rectangle allocation;
Ander Conselvan de Oliveira8e37d962014-05-08 14:55:50 +03001090 int tx, ty;
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001091
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001092 if (!entry->button_pressed) {
1093 return CURSOR_IBEAM;
1094 }
1095
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001096 widget_get_allocation(entry->widget, &allocation);
1097
Ander Conselvan de Oliveira8e37d962014-05-08 14:55:50 +03001098 tx = x - allocation.x - text_offset_left(&allocation);
1099 ty = y - allocation.y - text_offset_top(&allocation);
1100
1101 text_entry_set_cursor_position(entry, tx, ty, false);
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001102
1103 return CURSOR_IBEAM;
1104}
1105
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001106static void
1107text_entry_button_handler(struct widget *widget,
1108 struct input *input, uint32_t time,
1109 uint32_t button,
1110 enum wl_pointer_button_state state, void *data)
1111{
1112 struct text_entry *entry = data;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001113 struct rectangle allocation;
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001114 struct editor *editor;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001115 int32_t x, y;
Jan Arne Petersen3489ba92013-01-16 21:26:47 +01001116 uint32_t result;
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001117
1118 widget_get_allocation(entry->widget, &allocation);
1119 input_get_position(input, &x, &y);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001120
Ander Conselvan de Oliveira8e37d962014-05-08 14:55:50 +03001121 x -= allocation.x + text_offset_left(&allocation);
1122 y -= allocation.y + text_offset_top(&allocation);
Jan Arne Petersen3489ba92013-01-16 21:26:47 +01001123
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001124 editor = window_get_user_data(entry->window);
1125
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001126 if (button == BTN_LEFT) {
1127 entry->button_pressed = (state == WL_POINTER_BUTTON_STATE_PRESSED);
Jan Arne Petersen3489ba92013-01-16 21:26:47 +01001128
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001129 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
1130 input_grab(input, entry->widget, button);
1131 else
1132 input_ungrab(input);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001133 }
1134
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001135 if (text_entry_has_preedit(entry)) {
1136 result = text_entry_try_invoke_preedit_action(entry, x, y, button, state);
1137
1138 if (result)
1139 return;
1140 }
Jan Arne Petersen7e634a02012-09-09 23:08:36 +02001141
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001142 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
1143 struct wl_seat *seat = input_get_seat(input);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001144
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001145 text_entry_activate(entry, seat);
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001146 editor->active_entry = entry;
Jan Arne Petersen0e5bd452012-09-09 23:08:38 +02001147
Jan Arne Petersen1c45b4a2013-05-30 13:57:01 +02001148 text_entry_set_cursor_position(entry, x, y, true);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001149 }
1150}
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001151
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001152static void
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -08001153text_entry_touch_handler(struct widget *widget, struct input *input,
1154 uint32_t serial, uint32_t time, int32_t id,
1155 float tx, float ty, void *data)
1156{
1157 struct text_entry *entry = data;
1158 struct wl_seat *seat = input_get_seat(input);
1159 struct rectangle allocation;
1160 struct editor *editor;
1161 int32_t x, y;
1162
1163 widget_get_allocation(entry->widget, &allocation);
1164
Ander Conselvan de Oliveira8e37d962014-05-08 14:55:50 +03001165 x = tx - (allocation.x + text_offset_left(&allocation));
1166 y = ty - (allocation.y + text_offset_top(&allocation));
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -08001167
1168 editor = window_get_user_data(entry->window);
1169 text_entry_activate(entry, seat);
1170 editor->active_entry = entry;
1171
1172 text_entry_set_cursor_position(entry, x, y, true);
1173}
1174
1175static void
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001176editor_button_handler(struct widget *widget,
1177 struct input *input, uint32_t time,
1178 uint32_t button,
1179 enum wl_pointer_button_state state, void *data)
1180{
1181 struct editor *editor = data;
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001182
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001183 if (button != BTN_LEFT) {
1184 return;
1185 }
Jan Arne Petersene829adc2012-08-10 16:47:22 +02001186
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001187 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
1188 struct wl_seat *seat = input_get_seat(input);
1189
Jan Arne Petersene829adc2012-08-10 16:47:22 +02001190 text_entry_deactivate(editor->entry, seat);
1191 text_entry_deactivate(editor->editor, seat);
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001192 editor->active_entry = NULL;
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001193 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001194}
1195
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -08001196static void
1197editor_touch_handler(struct widget *widget, struct input *input,
1198 uint32_t serial, uint32_t time, int32_t id,
1199 float tx, float ty, void *data)
1200{
1201 struct editor *editor = data;
1202
1203 struct wl_seat *seat = input_get_seat(input);
1204
1205 text_entry_deactivate(editor->entry, seat);
1206 text_entry_deactivate(editor->editor, seat);
1207 editor->active_entry = NULL;
1208}
Kristian Høgsberg78858902014-01-01 23:57:42 -08001209
1210static void
1211keyboard_focus_handler(struct window *window,
1212 struct input *device, void *data)
1213{
1214 struct editor *editor = data;
1215
1216 window_schedule_redraw(editor->window);
1217}
1218
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001219static void
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001220key_handler(struct window *window,
1221 struct input *input, uint32_t time,
1222 uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
1223 void *data)
1224{
1225 struct editor *editor = data;
1226 struct text_entry *entry;
Jan Arne Petersen68516862013-04-18 16:47:42 +02001227 const char *new_char;
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001228 char text[16];
1229
1230 if (!editor->active_entry)
1231 return;
1232
1233 entry = editor->active_entry;
1234
1235 if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
1236 return;
1237
1238 switch (sym) {
1239 case XKB_KEY_BackSpace:
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +01001240 text_entry_commit_and_reset(entry);
1241
Jan Arne Petersen68516862013-04-18 16:47:42 +02001242 new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
1243 if (new_char != NULL)
1244 text_entry_delete_text(entry,
1245 new_char - entry->text,
1246 (entry->text + entry->cursor) - new_char);
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001247 break;
1248 case XKB_KEY_Delete:
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +01001249 text_entry_commit_and_reset(entry);
1250
Jan Arne Petersen68516862013-04-18 16:47:42 +02001251 new_char = utf8_next_char(entry->text + entry->cursor);
1252 if (new_char != NULL)
1253 text_entry_delete_text(entry,
1254 entry->cursor,
1255 new_char - (entry->text + entry->cursor));
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001256 break;
1257 case XKB_KEY_Left:
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +01001258 text_entry_commit_and_reset(entry);
1259
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001260 new_char = utf8_prev_char(entry->text, entry->text + entry->cursor);
1261 if (new_char != NULL) {
1262 entry->cursor = new_char - entry->text;
Rob Bradford70002832013-07-11 16:00:00 +01001263 if (!(input_get_modifiers(input) & MOD_SHIFT_MASK))
1264 entry->anchor = entry->cursor;
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001265 widget_schedule_redraw(entry->widget);
1266 }
1267 break;
1268 case XKB_KEY_Right:
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +01001269 text_entry_commit_and_reset(entry);
1270
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001271 new_char = utf8_next_char(entry->text + entry->cursor);
1272 if (new_char != NULL) {
1273 entry->cursor = new_char - entry->text;
Rob Bradford70002832013-07-11 16:00:00 +01001274 if (!(input_get_modifiers(input) & MOD_SHIFT_MASK))
1275 entry->anchor = entry->cursor;
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001276 widget_schedule_redraw(entry->widget);
1277 }
1278 break;
Manuel Bachmann8986c182014-04-18 12:50:14 +02001279 case XKB_KEY_Up:
1280 text_entry_commit_and_reset(entry);
1281
1282 move_up(entry->text, &entry->cursor);
1283 if (!(input_get_modifiers(input) & MOD_SHIFT_MASK))
1284 entry->anchor = entry->cursor;
1285 widget_schedule_redraw(entry->widget);
1286 break;
1287 case XKB_KEY_Down:
1288 text_entry_commit_and_reset(entry);
1289
1290 move_down(entry->text, &entry->cursor);
1291 if (!(input_get_modifiers(input) & MOD_SHIFT_MASK))
1292 entry->anchor = entry->cursor;
1293 widget_schedule_redraw(entry->widget);
1294 break;
Peter Maatman08c38d42013-07-06 20:42:59 +02001295 case XKB_KEY_Escape:
1296 break;
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001297 default:
1298 if (xkb_keysym_to_utf8(sym, text, sizeof(text)) <= 0)
1299 break;
1300
Peter Maatman08c38d42013-07-06 20:42:59 +02001301 text_entry_commit_and_reset(entry);
Jan Arne Petersen4a17fae2013-01-16 21:26:40 +01001302
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +01001303 text_entry_insert_at_cursor(entry, text, 0, 0);
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001304 break;
1305 }
1306
1307 widget_schedule_redraw(entry->widget);
1308}
1309
1310static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001311global_handler(struct display *display, uint32_t name,
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001312 const char *interface, uint32_t version, void *data)
1313{
1314 struct editor *editor = data;
1315
Jan Arne Petersen62ece762013-04-18 16:47:36 +02001316 if (!strcmp(interface, "wl_text_input_manager")) {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +02001317 editor->text_input_manager =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001318 display_bind(display, name,
Jan Arne Petersen62ece762013-04-18 16:47:36 +02001319 &wl_text_input_manager_interface, 1);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001320 }
1321}
1322
1323int
1324main(int argc, char *argv[])
1325{
1326 struct editor editor;
Jan Arne Petersen61381972013-01-31 15:52:21 +01001327 int i;
1328 uint32_t click_to_show = 0;
Jan Arne Petersen9d419132013-04-18 16:47:16 +02001329 const char *preferred_language = NULL;
Jan Arne Petersen61381972013-01-31 15:52:21 +01001330
Jan Arne Petersen9d419132013-04-18 16:47:16 +02001331 for (i = 1; i < argc; i++) {
Jan Arne Petersen61381972013-01-31 15:52:21 +01001332 if (strcmp("--click-to-show", argv[i]) == 0)
1333 click_to_show = 1;
Bill Spitzakbb0bb9c2014-08-08 12:59:58 -07001334 else if (strcmp("--preferred-language", argv[i]) == 0 &&
1335 i + 1 < argc) {
1336 preferred_language = argv[i + 1];
1337 i++;
1338 } else {
1339 printf("Usage: %s [OPTIONS]\n"
1340 " --click-to-show\n"
1341 " --preferred-language LANGUAGE\n",
1342 argv[0]);
1343 return 1;
Jan Arne Petersen9d419132013-04-18 16:47:16 +02001344 }
1345 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001346
Jan Arne Petersen25f6db52012-11-05 03:26:40 +01001347 memset(&editor, 0, sizeof editor);
1348
Jan Arne Petersen0a1cf392013-01-16 21:26:42 +01001349#ifdef HAVE_PANGO
1350 g_type_init();
1351#endif
1352
Kristian Høgsberg4172f662013-02-20 15:27:49 -05001353 editor.display = display_create(&argc, argv);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001354 if (editor.display == NULL) {
1355 fprintf(stderr, "failed to create display: %m\n");
1356 return -1;
1357 }
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001358
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001359 display_set_user_data(editor.display, &editor);
1360 display_set_global_handler(editor.display, global_handler);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001361
Olivier Blin30e1f3c2014-09-16 19:13:17 +02001362 if (editor.text_input_manager == NULL) {
1363 fprintf(stderr, "No text input manager global\n");
1364 return -1;
1365 }
1366
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001367 editor.window = window_create(editor.display);
Jason Ekstrandee7fefc2013-10-13 19:08:38 -05001368 editor.widget = window_frame_create(editor.window, &editor);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001369
1370 editor.entry = text_entry_create(&editor, "Entry");
Jan Arne Petersen61381972013-01-31 15:52:21 +01001371 editor.entry->click_to_show = click_to_show;
Jan Arne Petersen9d419132013-04-18 16:47:16 +02001372 if (preferred_language)
1373 editor.entry->preferred_language = strdup(preferred_language);
Jan Arne Petersen0558a932013-01-16 21:26:45 +01001374 editor.editor = text_entry_create(&editor, "Numeric");
Jan Arne Petersen62ece762013-04-18 16:47:36 +02001375 editor.editor->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
Jan Arne Petersen61381972013-01-31 15:52:21 +01001376 editor.editor->click_to_show = click_to_show;
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001377
1378 window_set_title(editor.window, "Text Editor");
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001379 window_set_key_handler(editor.window, key_handler);
Kristian Høgsberg78858902014-01-01 23:57:42 -08001380 window_set_keyboard_focus_handler(editor.window,
1381 keyboard_focus_handler);
Rob Bradford9d1d32b2012-11-18 19:06:49 +01001382 window_set_user_data(editor.window, &editor);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001383
1384 widget_set_redraw_handler(editor.widget, redraw_handler);
1385 widget_set_resize_handler(editor.widget, resize_handler);
Jan Arne Petersenf80bc062012-09-09 23:08:34 +02001386 widget_set_button_handler(editor.widget, editor_button_handler);
Kristian Høgsberg966e3ed2014-01-07 10:41:50 -08001387 widget_set_touch_down_handler(editor.widget, editor_touch_handler);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001388
1389 window_schedule_resize(editor.window, 500, 400);
1390
1391 display_run(editor.display);
1392
1393 text_entry_destroy(editor.entry);
1394 text_entry_destroy(editor.editor);
vivek31732f72014-05-15 18:58:16 +05301395 widget_destroy(editor.widget);
1396 window_destroy(editor.window);
1397 display_destroy(editor.display);
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001398
1399 return 0;
1400}