client: Fix shell unstable version check
[profile/ivi/weston-ivi-shell.git] / clients / calibrator.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <cairo.h>
28 #include <math.h>
29 #include <assert.h>
30
31 #include <linux/input.h>
32 #include <wayland-client.h>
33
34 #include "window.h"
35 #include "../shared/matrix.h"
36
37 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
38
39 /* Our points for the calibration must be not be on a line */
40 static const struct {
41         float x_ratio, y_ratio;
42 } test_ratios[] =  {
43         { 0.20, 0.40 },
44         { 0.80, 0.60 },
45         { 0.40, 0.80 }
46 };
47
48 struct calibrator {
49         struct tests {
50                 int32_t drawn_x, drawn_y;
51                 int32_t clicked_x, clicked_y;
52         } tests[ARRAY_LENGTH(test_ratios)];
53         int current_test;
54
55         struct display *display;
56         struct window *window;
57         struct widget *widget;
58 };
59
60 /*
61  * Calibration algorithm:
62  *
63  * The equation we want to apply at event time where x' and y' are the
64  * calibrated co-ordinates.
65  *
66  * x' = Ax + By + C
67  * y' = Dx + Ey + F
68  *
69  * For example "zero calibration" would be A=1.0 B=0.0 C=0.0, D=0.0, E=1.0,
70  * and F=0.0.
71  *
72  * With 6 unknowns we need 6 equations to find the constants:
73  *
74  * x1' = Ax1 + By1 + C
75  * y1' = Dx1 + Ey1 + F
76  * ...
77  * x3' = Ax3 + By3 + C
78  * y3' = Dx3 + Ey3 + F
79  *
80  * In matrix form:
81  *
82  * x1'   x1 y1 1      A
83  * x2' = x2 y2 1  x   B
84  * x3'   x3 y3 1      C
85  *
86  * So making the matrix M we can find the constants with:
87  *
88  * A            x1'
89  * B = M^-1  x  x2'
90  * C            x3'
91  *
92  * (and similarly for D, E and F)
93  *
94  * For the calibration the desired values x, y are the same values at which
95  * we've drawn at.
96  *
97  */
98 static void
99 finish_calibration (struct calibrator *calibrator)
100 {
101         struct weston_matrix m;
102         struct weston_matrix inverse;
103         struct weston_vector x_calib, y_calib;
104         int i;
105
106
107         /*
108          * x1 y1  1  0
109          * x2 y2  1  0
110          * x3 y3  1  0
111          *  0  0  0  1
112          */
113         memset(&m, 0, sizeof(m));
114         for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
115                 m.d[i] = calibrator->tests[i].clicked_x;
116                 m.d[i + 4] = calibrator->tests[i].clicked_y;
117                 m.d[i + 8] = 1;
118         }
119         m.d[15] = 1;
120
121         weston_matrix_invert(&inverse, &m);
122
123         memset(&x_calib, 0, sizeof(x_calib));
124         memset(&y_calib, 0, sizeof(y_calib));
125
126         for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
127                 x_calib.f[i] = calibrator->tests[i].drawn_x;
128                 y_calib.f[i] = calibrator->tests[i].drawn_y;
129         }
130
131         /* Multiples into the vector */
132         weston_matrix_transform(&inverse, &x_calib);
133         weston_matrix_transform(&inverse, &y_calib);
134
135         printf ("Calibration values: %f %f %f %f %f %f\n",
136                 x_calib.f[0], x_calib.f[1], x_calib.f[2],
137                 y_calib.f[0], y_calib.f[1], y_calib.f[2]);
138
139         exit(0);
140 }
141
142
143 static void
144 button_handler(struct widget *widget,
145                struct input *input, uint32_t time,
146                uint32_t button,
147                enum wl_pointer_button_state state, void *data)
148 {
149         struct calibrator *calibrator = data;
150         int32_t x, y;
151
152         if (state == WL_POINTER_BUTTON_STATE_PRESSED && button == BTN_LEFT) {
153                 input_get_position(input, &x, &y);
154                 calibrator->tests[calibrator->current_test].clicked_x = x;
155                 calibrator->tests[calibrator->current_test].clicked_y = y;
156
157                 calibrator->current_test--;
158                 if (calibrator->current_test < 0)
159                         finish_calibration(calibrator);
160         }
161
162         widget_schedule_redraw(widget);
163 }
164
165 static void
166 touch_handler(struct widget *widget, struct input *input, uint32_t serial,
167               uint32_t time, int32_t id, float x, float y, void *data)
168 {
169         struct calibrator *calibrator = data;
170
171         calibrator->tests[calibrator->current_test].clicked_x = x;
172         calibrator->tests[calibrator->current_test].clicked_y = y;
173         calibrator->current_test--;
174
175         if (calibrator->current_test < 0)
176                   finish_calibration(calibrator);
177
178         widget_schedule_redraw(widget);
179 }
180
181 static void
182 redraw_handler(struct widget *widget, void *data)
183 {
184         struct calibrator *calibrator = data;
185         struct rectangle allocation;
186         cairo_surface_t *surface;
187         cairo_t *cr;
188         int32_t drawn_x, drawn_y;
189
190         widget_get_allocation(calibrator->widget, &allocation);
191         surface = window_get_surface(calibrator->window);
192
193         cr = cairo_create(surface);
194         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
195         cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
196         cairo_paint(cr);
197
198         drawn_x = test_ratios[calibrator->current_test].x_ratio * allocation.width;
199         drawn_y = test_ratios[calibrator->current_test].y_ratio * allocation.height;
200
201         calibrator->tests[calibrator->current_test].drawn_x = drawn_x;
202         calibrator->tests[calibrator->current_test].drawn_y = drawn_y;
203
204         cairo_translate(cr, drawn_x, drawn_y);
205         cairo_set_line_width(cr, 2.0);
206         cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
207         cairo_move_to(cr, 0, -10.0);
208         cairo_line_to(cr, 0, 10.0);
209         cairo_stroke(cr);
210         cairo_move_to(cr, -10.0, 0);
211         cairo_line_to(cr, 10.0, 0.0);
212         cairo_stroke(cr);
213
214         cairo_destroy(cr);
215         cairo_surface_destroy(surface);
216 }
217
218 static struct calibrator *
219 calibrator_create(struct display *display)
220 {
221         struct calibrator *calibrator;
222
223         calibrator = malloc(sizeof *calibrator);
224         if (calibrator == NULL)
225                 return NULL;
226
227         calibrator->window = window_create(display);
228         calibrator->widget = window_add_widget(calibrator->window, calibrator);
229         window_set_title(calibrator->window, "Wayland calibrator");
230         calibrator->display = display;
231
232         calibrator->current_test = ARRAY_LENGTH(test_ratios) - 1;
233
234         widget_set_button_handler(calibrator->widget, button_handler);
235         widget_set_touch_down_handler(calibrator->widget, touch_handler);
236         widget_set_redraw_handler(calibrator->widget, redraw_handler);
237
238         window_set_fullscreen(calibrator->window, 1);
239
240         return calibrator;
241 }
242
243 static void
244 calibrator_destroy(struct calibrator *calibrator)
245 {
246         widget_destroy(calibrator->widget);
247         window_destroy(calibrator->window);
248         free(calibrator);
249 }
250
251
252 int
253 main(int argc, char *argv[])
254 {
255         struct display *display;
256         struct calibrator *calibrator;
257
258         display = display_create(&argc, argv);
259
260         if (display == NULL) {
261                 fprintf(stderr, "failed to create display: %m\n");
262                 return -1;
263         }
264
265         calibrator = calibrator_create(display);
266
267         if (!calibrator)
268                 return -1;
269
270         display_run(display);
271
272         calibrator_destroy(calibrator);
273         display_destroy(display);
274
275         return 0;
276 }
277