blob: c940c6fca8a819d8a417479674131dff727b43cb [file] [log] [blame]
Jan Arne Petersencba9e472012-06-21 21:52:19 +02001/*
2 * Copyright © 2012 Openismus GmbH
Jan Arne Petersen620cd622012-09-09 23:08:32 +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
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 "text-client-protocol.h"
33#include "desktop-shell-client-protocol.h"
34
35struct virtual_keyboard {
36 struct input_panel *input_panel;
37 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020038 struct input_method_context *context;
Jan Arne Petersencba9e472012-06-21 21:52:19 +020039 struct display *display;
40};
41
42struct keyboard {
43 struct virtual_keyboard *keyboard;
44 struct window *window;
45 struct widget *widget;
46 int cx;
47 int cy;
48};
49
50static void
51redraw_handler(struct widget *widget, void *data)
52{
53 struct keyboard *keyboard = data;
54 cairo_surface_t *surface;
55 struct rectangle allocation;
56 cairo_t *cr;
57 int cx, cy;
58 int i;
59
60 surface = window_get_surface(keyboard->window);
61 widget_get_allocation(keyboard->widget, &allocation);
62
63 cr = cairo_create(surface);
64 cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
65 cairo_clip(cr);
66
67 cairo_translate(cr, allocation.x, allocation.y);
68
69 cx = keyboard->cx;
70 cy = keyboard->cy;
71
72 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
73 cairo_set_source_rgba(cr, 1, 1, 1, 0.5);
74 cairo_rectangle(cr, 0, 0, 10 * cx, 5 * cy);
75 cairo_paint(cr);
76
77 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
78
79 for (i = 0; i <= 'Z' - '0'; ++i) {
80 const int x = i % 10;
81 const int y = i / 10;
82 char text[] = { i + '0', '\0' };
83 cairo_text_extents_t extents;
84 int dx, dy;
85
86 cairo_text_extents(cr, text, &extents);
87 dx = extents.width;
88 dy = extents.height;
89
90 cairo_set_source_rgb(cr, 0, 0, 0);
91 cairo_rectangle(cr, x * cx, y * cy, cx, cy);
92 cairo_stroke(cr);
93
94 cairo_move_to(cr, x * cx + 0.5 * (cx - dx), y * cy + 0.5 * (cy - dy));
95
96 cairo_set_source_rgb(cr, 0, 0, 0);
97 cairo_show_text(cr, text);
98 }
99
100 cairo_destroy(cr);
101 cairo_surface_destroy(surface);
102}
103
104static void
105resize_handler(struct widget *widget,
106 int32_t width, int32_t height, void *data)
107{
108 /* struct keyboard *keyboard = data; */
109}
110
111static void
112button_handler(struct widget *widget,
113 struct input *input, uint32_t time,
114 uint32_t button,
115 enum wl_pointer_button_state state, void *data)
116{
117 struct keyboard *keyboard = data;
118 struct rectangle allocation;
119 int32_t x, y;
120 char text[] = { '0', '\0' };
121
122 if (state != WL_POINTER_BUTTON_STATE_PRESSED || button != BTN_LEFT) {
123 return;
124 }
125
126 input_get_position(input, &x, &y);
127
128 widget_get_allocation(keyboard->widget, &allocation);
129 x -= allocation.x;
130 y -= allocation.y;
131
132 text[0] = y / keyboard->cy * 10 + x / keyboard->cx + '0';
133
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200134 input_method_context_commit_string(keyboard->keyboard->context, text, -1);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200135
136 widget_schedule_redraw(widget);
137}
138
139static void
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200140input_method_context_surrounding_text(void *data,
141 struct input_method_context *context,
142 const char *text,
143 uint32_t cursor,
144 uint32_t anchor)
145{
146 fprintf(stderr, "Surrounding text updated: %s\n", text);
147}
148
149static const struct input_method_context_listener input_method_context_listener = {
150 input_method_context_surrounding_text,
151};
152
153static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200154input_method_activate(void *data,
155 struct input_method *input_method,
156 struct input_method_context *context)
157{
158 struct virtual_keyboard *keyboard = data;
159
160 if (keyboard->context)
161 input_method_context_destroy(keyboard->context);
162
163 keyboard->context = context;
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200164 input_method_context_add_listener(context,
165 &input_method_context_listener,
166 keyboard);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200167}
168
169static void
170input_method_deactivate(void *data,
171 struct input_method *input_method,
172 struct input_method_context *context)
173{
174 struct virtual_keyboard *keyboard = data;
175
176 if (!keyboard->context)
177 return;
178
179 input_method_context_destroy(keyboard->context);
180 keyboard->context = NULL;
181}
182
183static const struct input_method_listener input_method_listener = {
184 input_method_activate,
185 input_method_deactivate
186};
187
188static void
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200189global_handler(struct wl_display *display, uint32_t id,
190 const char *interface, uint32_t version, void *data)
191{
192 struct virtual_keyboard *keyboard = data;
193
194 if (!strcmp(interface, "input_panel")) {
195 keyboard->input_panel = wl_display_bind(display, id, &input_panel_interface);
196 } else if (!strcmp(interface, "input_method")) {
197 keyboard->input_method = wl_display_bind(display, id, &input_method_interface);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200198 input_method_add_listener(keyboard->input_method, &input_method_listener, keyboard);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200199 }
200}
201
202static void
203keyboard_create(struct output *output, struct virtual_keyboard *virtual_keyboard)
204{
205 struct keyboard *keyboard;
206
207 keyboard = malloc(sizeof *keyboard);
208 memset(keyboard, 0, sizeof *keyboard);
209
210 keyboard->keyboard = virtual_keyboard;
Kristian Høgsberg0636ac32012-06-27 10:22:15 -0400211 keyboard->window = window_create_custom(virtual_keyboard->display);
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200212 keyboard->widget = window_add_widget(keyboard->window, keyboard);
213
214 window_set_title(keyboard->window, "Virtual keyboard");
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200215 window_set_user_data(keyboard->window, keyboard);
216
217 keyboard->cx = 40;
218 keyboard->cy = 40;
219
220 widget_set_redraw_handler(keyboard->widget, redraw_handler);
221 widget_set_resize_handler(keyboard->widget, resize_handler);
222 widget_set_button_handler(keyboard->widget, button_handler);
223
224 window_schedule_resize(keyboard->window, keyboard->cx * 10, keyboard->cy * 5);
225
226 input_panel_set_surface(virtual_keyboard->input_panel,
Kristian Høgsberg0636ac32012-06-27 10:22:15 -0400227 window_get_wl_surface(keyboard->window),
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200228 output_get_wl_output(output));
229}
230
231static void
232handle_output_configure(struct output *output, void *data)
233{
234 struct virtual_keyboard *virtual_keyboard = data;
235
236 /* skip existing outputs */
237 if (output_get_user_data(output))
238 return;
239
240 output_set_user_data(output, virtual_keyboard);
241
242 keyboard_create(output, virtual_keyboard);
243}
244
245int
246main(int argc, char *argv[])
247{
248 struct virtual_keyboard virtual_keyboard;
249
250 virtual_keyboard.display = display_create(argc, argv);
251 if (virtual_keyboard.display == NULL) {
252 fprintf(stderr, "failed to create display: %m\n");
253 return -1;
254 }
255
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200256 virtual_keyboard.context = NULL;
257
Jan Arne Petersencba9e472012-06-21 21:52:19 +0200258 wl_display_add_global_listener(display_get_display(virtual_keyboard.display),
259 global_handler, &virtual_keyboard);
260
261 display_set_user_data(virtual_keyboard.display, &virtual_keyboard);
262 display_set_output_configure_handler(virtual_keyboard.display, handle_output_configure);
263
264 display_run(virtual_keyboard.display);
265
266 return 0;
267}