keyboard: Use a qwerty virtual keyboard layout
[profile/ivi/weston-ivi-shell.git] / clients / keyboard.c
1 /*
2  * Copyright © 2012 Openismus GmbH
3  * Copyright © 2012 Intel Corporation
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of the copyright holders not be used in
10  * advertising or publicity pertaining to distribution of the software
11  * without specific, written prior permission.  The copyright holders make
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <linux/input.h>
29 #include <cairo.h>
30
31 #include "window.h"
32 #include "input-method-client-protocol.h"
33 #include "desktop-shell-client-protocol.h"
34
35 struct virtual_keyboard {
36         struct input_panel *input_panel;
37         struct input_method *input_method;
38         struct input_method_context *context;
39         struct display *display;
40 };
41
42 enum key_type {
43         keytype_default,
44         keytype_backspace,
45         keytype_enter,
46         keytype_space,
47         keytype_switch,
48         keytype_symbols,
49         keytype_tab
50 };
51
52 struct key {
53         enum key_type key_type;
54
55         char *label;
56         char *alt;
57
58         unsigned int width;
59 };
60
61 static const struct key keys[] = {
62         { keytype_default, "q", "Q", 1},
63         { keytype_default, "w", "W", 1},
64         { keytype_default, "e", "E", 1},
65         { keytype_default, "r", "R", 1},
66         { keytype_default, "t", "T", 1},
67         { keytype_default, "y", "Y", 1},
68         { keytype_default, "u", "U", 1},
69         { keytype_default, "i", "I", 1},
70         { keytype_default, "o", "O", 1},
71         { keytype_default, "p", "P", 1},
72         { keytype_backspace, "<--", "<--", 2},
73
74         { keytype_tab, "->|", "->|", 1},
75         { keytype_default, "a", "A", 1},
76         { keytype_default, "s", "S", 1},
77         { keytype_default, "d", "D", 1},
78         { keytype_default, "f", "F", 1},
79         { keytype_default, "g", "G", 1},
80         { keytype_default, "h", "H", 1},
81         { keytype_default, "j", "J", 1},
82         { keytype_default, "k", "K", 1},
83         { keytype_default, "l", "L", 1},
84         { keytype_enter, "Enter", "Enter", 2},
85
86         { keytype_switch, "ABC", "abc", 2},
87         { keytype_default, "z", "Z", 1},
88         { keytype_default, "x", "X", 1},
89         { keytype_default, "c", "C", 1},
90         { keytype_default, "v", "V", 1},
91         { keytype_default, "b", "B", 1},
92         { keytype_default, "n", "N", 1},
93         { keytype_default, "m", "M", 1},
94         { keytype_default, ",", ",", 1},
95         { keytype_default, ".", ".", 1},
96         { keytype_switch, "ABC", "abc", 1},
97
98         { keytype_symbols, "?123", "?123", 2},
99         { keytype_space, "", "", 8},
100         { keytype_symbols, "?123", "?123", 2}
101 };
102
103 static const unsigned int columns = 12;
104 static const unsigned int rows = 4;
105
106 static const double key_width = 60;
107 static const double key_height = 50;
108
109 enum keyboard_state {
110         keyboardstate_default,
111         keyboardstate_uppercase
112 };
113
114 struct keyboard {
115         struct virtual_keyboard *keyboard;
116         struct window *window;
117         struct widget *widget;
118
119         enum keyboard_state state;
120 };
121
122 static void
123 draw_key(const struct key *key,
124          cairo_t *cr,
125          enum keyboard_state state,
126          unsigned int row,
127          unsigned int col)
128 {
129         const char *label;
130         cairo_text_extents_t extents;
131
132         cairo_save(cr);
133         cairo_rectangle(cr,
134                         col * key_width, row * key_height,
135                         key->width * key_width, key_height);
136         cairo_clip(cr);
137
138         /* Paint frame */
139         cairo_rectangle(cr,
140                         col * key_width, row * key_height,
141                         key->width * key_width, key_height);
142         cairo_set_line_width(cr, 3);
143         cairo_stroke(cr);
144
145         /* Paint text */
146         label = state == keyboardstate_default ? key->label : key->alt;
147         cairo_text_extents(cr, label, &extents);
148
149         cairo_translate(cr,
150                         col * key_width,
151                         row * key_height);
152         cairo_translate(cr,
153                         (key->width * key_width - extents.width) / 2,
154                         (key_height - extents.y_bearing) / 2);
155         cairo_show_text(cr, label);
156
157         cairo_restore(cr);
158 }
159
160 static void
161 redraw_handler(struct widget *widget, void *data)
162 {
163         struct keyboard *keyboard = data;
164         cairo_surface_t *surface;
165         struct rectangle allocation;
166         cairo_t *cr;
167         unsigned int i;
168         unsigned int row = 0, col = 0;
169
170         surface = window_get_surface(keyboard->window);
171         widget_get_allocation(keyboard->widget, &allocation);
172
173         cr = cairo_create(surface);
174         cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
175         cairo_clip(cr);
176
177         cairo_select_font_face(cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
178         cairo_set_font_size(cr, 16);
179
180         cairo_translate(cr, allocation.x, allocation.y);
181
182         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
183         cairo_set_source_rgba(cr, 1, 1, 1, 0.75);
184         cairo_rectangle(cr, 0, 0, columns * key_width, rows * key_height);
185         cairo_paint(cr);
186
187         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
188
189         for (i = 0; i < sizeof(keys) / sizeof(*keys); ++i) {
190                 cairo_set_source_rgb(cr, 0, 0, 0);
191                 draw_key(&keys[i], cr, keyboard->state, row, col);
192                 col += keys[i].width;
193                 if (col >= columns) {
194                         row += 1;
195                         col = 0;
196                 }
197         }
198
199         cairo_destroy(cr);
200         cairo_surface_destroy(surface);
201 }
202
203 static void
204 resize_handler(struct widget *widget,
205                int32_t width, int32_t height, void *data)
206 {
207         /* struct keyboard *keyboard = data; */
208 }
209
210 static void
211 keyboard_handle_key(struct keyboard *keyboard, const struct key *key)
212 {
213         const char *label = keyboard->state == keyboardstate_default ? key->label : key->alt;
214
215         switch (key->key_type) {
216                 case keytype_default:
217                         input_method_context_commit_string(keyboard->keyboard->context,
218                                                            label, -1);
219                         break;
220                 case keytype_backspace:
221                         break;
222                 case keytype_enter:
223                         break;
224                 case keytype_space:
225                         input_method_context_commit_string(keyboard->keyboard->context,
226                                                            " ", -1);
227                         break;
228                 case keytype_switch:
229                         if (keyboard->state == keyboardstate_default)
230                                 keyboard->state = keyboardstate_uppercase;
231                         else
232                                 keyboard->state = keyboardstate_default;
233                         break;
234                 case keytype_symbols:
235                         break;
236                 case keytype_tab:
237                         break;
238         }
239 }
240
241 static void
242 button_handler(struct widget *widget,
243                struct input *input, uint32_t time,
244                uint32_t button,
245                enum wl_pointer_button_state state, void *data)
246 {
247         struct keyboard *keyboard = data;
248         struct rectangle allocation;
249         int32_t x, y;
250         int row, col;
251         unsigned int i;
252
253         if (state != WL_POINTER_BUTTON_STATE_PRESSED || button != BTN_LEFT) {
254                 return;
255         }
256
257         input_get_position(input, &x, &y);
258
259         widget_get_allocation(keyboard->widget, &allocation);
260         x -= allocation.x;
261         y -= allocation.y;
262
263         row = y / key_height;
264         col = x / key_width + row * columns;
265         for (i = 0; i < sizeof(keys) / sizeof(*keys); ++i) {
266                 col -= keys[i].width;
267                 if (col < 0)
268                         break;
269         }
270
271         keyboard_handle_key(keyboard, &keys[i]);
272
273         widget_schedule_redraw(widget);
274 }
275
276 static void
277 input_method_context_surrounding_text(void *data,
278                                       struct input_method_context *context,
279                                       const char *text,
280                                       uint32_t cursor,
281                                       uint32_t anchor)
282 {
283         fprintf(stderr, "Surrounding text updated: %s\n", text);
284 }
285
286 static const struct input_method_context_listener input_method_context_listener = {
287         input_method_context_surrounding_text,
288 };
289
290 static void
291 input_method_activate(void *data,
292                       struct input_method *input_method,
293                       struct input_method_context *context)
294 {
295         struct virtual_keyboard *keyboard = data;
296
297         if (keyboard->context)
298                 input_method_context_destroy(keyboard->context);
299
300         keyboard->context = context;
301         input_method_context_add_listener(context,
302                                           &input_method_context_listener,
303                                           keyboard);
304 }
305
306 static void
307 input_method_deactivate(void *data,
308                         struct input_method *input_method,
309                         struct input_method_context *context)
310 {
311         struct virtual_keyboard *keyboard = data;
312
313         if (!keyboard->context)
314                 return;
315
316         input_method_context_destroy(keyboard->context);
317         keyboard->context = NULL;
318 }
319
320 static const struct input_method_listener input_method_listener = {
321         input_method_activate,
322         input_method_deactivate
323 };
324
325 static void
326 global_handler(struct wl_display *display, uint32_t id,
327                const char *interface, uint32_t version, void *data)
328 {
329         struct virtual_keyboard *keyboard = data;
330
331         if (!strcmp(interface, "input_panel")) {
332                 keyboard->input_panel = wl_display_bind(display, id, &input_panel_interface);
333         } else if (!strcmp(interface, "input_method")) {
334                 keyboard->input_method = wl_display_bind(display, id, &input_method_interface);
335                 input_method_add_listener(keyboard->input_method, &input_method_listener, keyboard);
336         }
337 }
338
339 static void
340 keyboard_create(struct output *output, struct virtual_keyboard *virtual_keyboard)
341 {
342         struct keyboard *keyboard;
343
344         keyboard = malloc(sizeof *keyboard);
345         memset(keyboard, 0, sizeof *keyboard);
346
347         keyboard->keyboard = virtual_keyboard;
348         keyboard->window = window_create_custom(virtual_keyboard->display);
349         keyboard->widget = window_add_widget(keyboard->window, keyboard);
350
351         window_set_title(keyboard->window, "Virtual keyboard");
352         window_set_user_data(keyboard->window, keyboard);
353
354         widget_set_redraw_handler(keyboard->widget, redraw_handler);
355         widget_set_resize_handler(keyboard->widget, resize_handler);
356         widget_set_button_handler(keyboard->widget, button_handler);
357
358         window_schedule_resize(keyboard->window,
359                                columns * key_width,
360                                rows * key_height);
361
362         input_panel_set_surface(virtual_keyboard->input_panel,
363                                 window_get_wl_surface(keyboard->window),
364                                 output_get_wl_output(output));
365 }
366
367 static void
368 handle_output_configure(struct output *output, void *data)
369 {
370         struct virtual_keyboard *virtual_keyboard = data;
371
372         /* skip existing outputs */
373         if (output_get_user_data(output))
374                 return;
375
376         output_set_user_data(output, virtual_keyboard);
377
378         keyboard_create(output, virtual_keyboard);
379 }
380
381 int
382 main(int argc, char *argv[])
383 {
384         struct virtual_keyboard virtual_keyboard;
385
386         virtual_keyboard.display = display_create(argc, argv);
387         if (virtual_keyboard.display == NULL) {
388                 fprintf(stderr, "failed to create display: %m\n");
389                 return -1;
390         }
391
392         virtual_keyboard.context = NULL;
393
394         wl_display_add_global_listener(display_get_display(virtual_keyboard.display),
395                                        global_handler, &virtual_keyboard);
396
397         display_set_user_data(virtual_keyboard.display, &virtual_keyboard);
398         display_set_output_configure_handler(virtual_keyboard.display, handle_output_configure);
399
400         display_run(virtual_keyboard.display);
401
402         return 0;
403 }