weston-editor --help works
[profile/ivi/weston-ivi-shell.git] / clients / clickdot.c
1 /*
2  * Copyright © 2010 Intel Corporation
3  * Copyright © 2012 Collabora, Ltd.
4  * Copyright © 2012 Jonas Ådahl
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that copyright
9  * notice and this permission notice appear in supporting documentation, and
10  * that the name of the copyright holders not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  The copyright holders make no representations
13  * about the suitability of this software for any purpose.  It is provided "as
14  * is" without express or implied warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22  * OF THIS SOFTWARE.
23  */
24
25 #include "config.h"
26
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <cairo.h>
32 #include <math.h>
33 #include <assert.h>
34
35 #include <linux/input.h>
36 #include <wayland-client.h>
37
38 #include "window.h"
39
40 struct clickdot {
41         struct display *display;
42         struct window *window;
43         struct widget *widget;
44
45         cairo_surface_t *buffer;
46
47         struct {
48                 int32_t x, y;
49         } dot;
50
51         struct {
52                 int32_t x, y;
53                 int32_t old_x, old_y;
54         } line;
55
56         int reset;
57 };
58
59 static void
60 draw_line(struct clickdot *clickdot, cairo_t *cr,
61           struct rectangle *allocation)
62 {
63         cairo_t *bcr;
64         cairo_surface_t *tmp_buffer = NULL;
65
66         if (clickdot->reset) {
67                 tmp_buffer = clickdot->buffer;
68                 clickdot->buffer = NULL;
69                 clickdot->line.x = -1;
70                 clickdot->line.y = -1;
71                 clickdot->line.old_x = -1;
72                 clickdot->line.old_y = -1;
73                 clickdot->reset = 0;
74         }
75
76         if (clickdot->buffer == NULL) {
77                 clickdot->buffer =
78                         cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
79                                                    allocation->width,
80                                                    allocation->height);
81                 bcr = cairo_create(clickdot->buffer);
82                 cairo_set_source_rgba(bcr, 0, 0, 0, 0);
83                 cairo_rectangle(bcr,
84                                 0, 0,
85                                 allocation->width, allocation->height);
86                 cairo_fill(bcr);
87         }
88         else
89                 bcr = cairo_create(clickdot->buffer);
90
91         if (tmp_buffer) {
92                 cairo_set_source_surface(bcr, tmp_buffer, 0, 0);
93                 cairo_rectangle(bcr, 0, 0,
94                                 allocation->width, allocation->height);
95                 cairo_clip(bcr);
96                 cairo_paint(bcr);
97
98                 cairo_surface_destroy(tmp_buffer);
99         }
100
101         if (clickdot->line.x != -1 && clickdot->line.y != -1) {
102                 if (clickdot->line.old_x != -1 &&
103                     clickdot->line.old_y != -1) {
104                         cairo_set_line_width(bcr, 2.0);
105                         cairo_set_source_rgb(bcr, 1, 1, 1);
106                         cairo_translate(bcr,
107                                         -allocation->x, -allocation->y);
108
109                         cairo_move_to(bcr,
110                                       clickdot->line.old_x,
111                                       clickdot->line.old_y);
112                         cairo_line_to(bcr,
113                                       clickdot->line.x,
114                                       clickdot->line.y);
115
116                         cairo_stroke(bcr);
117                 }
118
119                 clickdot->line.old_x = clickdot->line.x;
120                 clickdot->line.old_y = clickdot->line.y;
121         }
122         cairo_destroy(bcr);
123
124         cairo_set_source_surface(cr, clickdot->buffer,
125                                  allocation->x, allocation->y);
126         cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
127         cairo_rectangle(cr,
128                         allocation->x, allocation->y,
129                         allocation->width, allocation->height);
130         cairo_clip(cr);
131         cairo_paint(cr);
132 }
133
134 static void
135 redraw_handler(struct widget *widget, void *data)
136 {
137         static const double r = 10.0;
138         struct clickdot *clickdot = data;
139         cairo_surface_t *surface;
140         cairo_t *cr;
141         struct rectangle allocation;
142
143         widget_get_allocation(clickdot->widget, &allocation);
144
145         surface = window_get_surface(clickdot->window);
146
147         cr = cairo_create(surface);
148         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
149         cairo_rectangle(cr,
150                         allocation.x,
151                         allocation.y,
152                         allocation.width,
153                         allocation.height);
154         cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
155         cairo_fill(cr);
156
157         draw_line(clickdot, cr, &allocation);
158
159         cairo_translate(cr, clickdot->dot.x + 0.5, clickdot->dot.y + 0.5);
160         cairo_set_line_width(cr, 1.0);
161         cairo_set_source_rgb(cr, 0.1, 0.9, 0.9);
162         cairo_move_to(cr, 0.0, -r);
163         cairo_line_to(cr, 0.0, r);
164         cairo_move_to(cr, -r, 0.0);
165         cairo_line_to(cr, r, 0.0);
166         cairo_arc(cr, 0.0, 0.0, r, 0.0, 2.0 * M_PI);
167         cairo_stroke(cr);
168
169         cairo_destroy(cr);
170
171         cairo_surface_destroy(surface);
172 }
173
174 static void
175 keyboard_focus_handler(struct window *window,
176                        struct input *device, void *data)
177 {
178         struct clickdot *clickdot = data;
179
180         window_schedule_redraw(clickdot->window);
181 }
182
183 static void
184 key_handler(struct window *window, struct input *input, uint32_t time,
185             uint32_t key, uint32_t sym,
186             enum wl_keyboard_key_state state, void *data)
187 {
188         struct clickdot *clickdot = data;
189
190         if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
191                 return;
192
193         switch (sym) {
194         case XKB_KEY_Escape:
195                 display_exit(clickdot->display);
196                 break;
197         }
198 }
199
200 static void
201 button_handler(struct widget *widget,
202                struct input *input, uint32_t time,
203                uint32_t button,
204                enum wl_pointer_button_state state, void *data)
205 {
206         struct clickdot *clickdot = data;
207
208         if (state == WL_POINTER_BUTTON_STATE_PRESSED && button == BTN_LEFT)
209                 input_get_position(input, &clickdot->dot.x, &clickdot->dot.y);
210
211         widget_schedule_redraw(widget);
212 }
213
214 static int
215 motion_handler(struct widget *widget,
216                struct input *input, uint32_t time,
217                float x, float y, void *data)
218 {
219         struct clickdot *clickdot = data;
220         clickdot->line.x = x;
221         clickdot->line.y = y;
222
223         window_schedule_redraw(clickdot->window);
224
225         return CURSOR_LEFT_PTR;
226 }
227
228 static void
229 resize_handler(struct widget *widget,
230                int32_t width, int32_t height,
231                void *data)
232 {
233         struct clickdot *clickdot = data;
234
235         clickdot->reset = 1;
236 }
237
238 static void
239 leave_handler(struct widget *widget,
240               struct input *input, void *data)
241 {
242         struct clickdot *clickdot = data;
243
244         clickdot->reset = 1;
245 }
246
247 static struct clickdot *
248 clickdot_create(struct display *display)
249 {
250         struct clickdot *clickdot;
251
252         clickdot = xzalloc(sizeof *clickdot);
253         clickdot->window = window_create(display);
254         clickdot->widget = window_frame_create(clickdot->window, clickdot);
255         window_set_title(clickdot->window, "Wayland ClickDot");
256         clickdot->display = display;
257         clickdot->buffer = NULL;
258
259         window_set_key_handler(clickdot->window, key_handler);
260         window_set_user_data(clickdot->window, clickdot);
261         window_set_keyboard_focus_handler(clickdot->window,
262                                           keyboard_focus_handler);
263
264         widget_set_redraw_handler(clickdot->widget, redraw_handler);
265         widget_set_button_handler(clickdot->widget, button_handler);
266         widget_set_motion_handler(clickdot->widget, motion_handler);
267         widget_set_resize_handler(clickdot->widget, resize_handler);
268         widget_set_leave_handler(clickdot->widget, leave_handler);
269
270         widget_schedule_resize(clickdot->widget, 500, 400);
271         clickdot->dot.x = 250;
272         clickdot->dot.y = 200;
273         clickdot->line.x = -1;
274         clickdot->line.y = -1;
275         clickdot->line.old_x = -1;
276         clickdot->line.old_y = -1;
277         clickdot->reset = 0;
278
279         return clickdot;
280 }
281
282 static void
283 clickdot_destroy(struct clickdot *clickdot)
284 {
285         if (clickdot->buffer)
286                 cairo_surface_destroy(clickdot->buffer);
287         widget_destroy(clickdot->widget);
288         window_destroy(clickdot->window);
289         free(clickdot);
290 }
291
292 int
293 main(int argc, char *argv[])
294 {
295         struct display *display;
296         struct clickdot *clickdot;
297
298         display = display_create(&argc, argv);
299         if (display == NULL) {
300                 fprintf(stderr, "failed to create display: %m\n");
301                 return -1;
302         }
303
304         clickdot = clickdot_create(display);
305
306         display_run(display);
307
308         clickdot_destroy(clickdot);
309         display_destroy(display);
310
311         return 0;
312 }