window: use libwayland-cursor instead of libXcursor
[platform/upstream/weston.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 <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <cairo.h>
30 #include <math.h>
31 #include <assert.h>
32
33 #include <linux/input.h>
34 #include <wayland-client.h>
35 #include <wayland-cursor.h>
36
37 #include "window.h"
38
39 struct clickdot {
40         struct display *display;
41         struct window *window;
42         struct widget *widget;
43
44         cairo_surface_t *buffer;
45
46         struct {
47                 int32_t x, y;
48         } dot;
49
50         struct {
51                 int32_t x, y;
52                 int32_t old_x, old_y;
53         } line;
54
55         int reset;
56 };
57
58 static void
59 draw_line(struct clickdot *clickdot, cairo_t *cr,
60           struct rectangle *allocation)
61 {
62         cairo_t *bcr;
63         cairo_surface_t *tmp_buffer = NULL;
64
65         if (clickdot->reset) {
66                 tmp_buffer = clickdot->buffer;
67                 clickdot->buffer = NULL;
68                 clickdot->line.x = -1;
69                 clickdot->line.y = -1;
70                 clickdot->line.old_x = -1;
71                 clickdot->line.old_y = -1;
72                 clickdot->reset = 0;
73         }
74
75         if (clickdot->buffer == NULL) {
76                 clickdot->buffer =
77                         cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
78                                                    allocation->width,
79                                                    allocation->height);
80                 bcr = cairo_create(clickdot->buffer);
81                 cairo_set_source_rgba(bcr, 0, 0, 0, 0);
82                 cairo_rectangle(bcr,
83                                 0, 0,
84                                 allocation->width, allocation->height);
85                 cairo_fill(bcr);
86         }
87         else
88                 bcr = cairo_create(clickdot->buffer);
89
90         if (tmp_buffer) {
91                 cairo_set_source_surface(bcr, tmp_buffer, 0, 0);
92                 cairo_rectangle(bcr, 0, 0,
93                                 allocation->width, allocation->height);
94                 cairo_clip(bcr);
95                 cairo_paint(bcr);
96
97                 cairo_surface_destroy(tmp_buffer);
98         }
99
100         if (clickdot->line.x != -1 && clickdot->line.y != -1) {
101                 if (clickdot->line.old_x != -1 &&
102                     clickdot->line.old_y != -1) {
103                         cairo_set_line_width(bcr, 2.0);
104                         cairo_set_source_rgb(bcr, 1, 1, 1);
105                         cairo_translate(bcr,
106                                         -allocation->x, -allocation->y);
107
108                         cairo_move_to(bcr,
109                                       clickdot->line.old_x,
110                                       clickdot->line.old_y);
111                         cairo_line_to(bcr,
112                                       clickdot->line.x,
113                                       clickdot->line.y);
114
115                         cairo_stroke(bcr);
116                 }
117
118                 clickdot->line.old_x = clickdot->line.x;
119                 clickdot->line.old_y = clickdot->line.y;
120         }
121         cairo_destroy(bcr);
122
123         cairo_set_source_surface(cr, clickdot->buffer,
124                                  allocation->x, allocation->y);
125         cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
126         cairo_rectangle(cr,
127                         allocation->x, allocation->y,
128                         allocation->width, allocation->height);
129         cairo_clip(cr);
130         cairo_paint(cr);
131 }
132
133 static void
134 redraw_handler(struct widget *widget, void *data)
135 {
136         static const double r = 10.0;
137         struct clickdot *clickdot = data;
138         cairo_surface_t *surface;
139         cairo_t *cr;
140         struct rectangle allocation;
141
142         widget_get_allocation(clickdot->widget, &allocation);
143
144         surface = window_get_surface(clickdot->window);
145
146         cr = cairo_create(surface);
147         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
148         cairo_rectangle(cr,
149                         allocation.x,
150                         allocation.y,
151                         allocation.width,
152                         allocation.height);
153         cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
154         cairo_fill(cr);
155
156         draw_line(clickdot, cr, &allocation);
157
158         cairo_translate(cr, clickdot->dot.x + 0.5, clickdot->dot.y + 0.5);
159         cairo_set_line_width(cr, 1.0);
160         cairo_set_source_rgb(cr, 0.1, 0.9, 0.9);
161         cairo_move_to(cr, 0.0, -r);
162         cairo_line_to(cr, 0.0, r);
163         cairo_move_to(cr, -r, 0.0);
164         cairo_line_to(cr, r, 0.0);
165         cairo_arc(cr, 0.0, 0.0, r, 0.0, 2.0 * M_PI);
166         cairo_stroke(cr);
167
168         cairo_destroy(cr);
169
170         cairo_surface_destroy(surface);
171 }
172
173 static void
174 keyboard_focus_handler(struct window *window,
175                        struct input *device, void *data)
176 {
177         struct clickdot *clickdot = data;
178
179         window_schedule_redraw(clickdot->window);
180 }
181
182 static void
183 key_handler(struct window *window, struct input *input, uint32_t time,
184             uint32_t key, uint32_t sym, uint32_t state, void *data)
185 {
186         struct clickdot *clickdot = data;
187
188         if (state == 0)
189                 return;
190
191         switch (sym) {
192         case XKB_KEY_Escape:
193                 display_exit(clickdot->display);
194                 break;
195         }
196 }
197
198 static void
199 button_handler(struct widget *widget,
200                struct input *input, uint32_t time,
201                uint32_t button, uint32_t state, void *data)
202 {
203         struct clickdot *clickdot = data;
204
205         if (state && button == BTN_LEFT)
206                 input_get_position(input, &clickdot->dot.x, &clickdot->dot.y);
207
208         widget_schedule_redraw(widget);
209 }
210
211 static int
212 motion_handler(struct widget *widget,
213                struct input *input, uint32_t time,
214                float x, float y, void *data)
215 {
216         struct clickdot *clickdot = data;
217         clickdot->line.x = x;
218         clickdot->line.y = y;
219
220         window_schedule_redraw(clickdot->window);
221
222         return WL_CURSOR_LEFT_PTR;
223 }
224
225 static void
226 resize_handler(struct widget *widget,
227                int32_t width, int32_t height,
228                void *data)
229 {
230         struct clickdot *clickdot = data;
231
232         clickdot->reset = 1;
233 }
234
235 static void
236 leave_handler(struct widget *widget,
237               struct input *input, void *data)
238 {
239         struct clickdot *clickdot = data;
240
241         clickdot->reset = 1;
242 }
243
244 static struct clickdot *
245 clickdot_create(struct display *display)
246 {
247         struct clickdot *clickdot;
248
249         clickdot = malloc(sizeof *clickdot);
250         if (clickdot == NULL)
251                 return clickdot;
252         memset(clickdot, 0, sizeof *clickdot);
253
254         clickdot->window = window_create(display);
255         clickdot->widget = frame_create(clickdot->window, clickdot);
256         window_set_title(clickdot->window, "Wayland ClickDot");
257         clickdot->display = display;
258         clickdot->buffer = NULL;
259
260         window_set_key_handler(clickdot->window, key_handler);
261         window_set_user_data(clickdot->window, clickdot);
262         window_set_keyboard_focus_handler(clickdot->window,
263                                           keyboard_focus_handler);
264
265         widget_set_redraw_handler(clickdot->widget, redraw_handler);
266         widget_set_button_handler(clickdot->widget, button_handler);
267         widget_set_motion_handler(clickdot->widget, motion_handler);
268         widget_set_resize_handler(clickdot->widget, resize_handler);
269         widget_set_leave_handler(clickdot->widget, leave_handler);
270
271         widget_schedule_resize(clickdot->widget, 500, 400);
272         clickdot->dot.x = 250;
273         clickdot->dot.y = 200;
274         clickdot->line.x = -1;
275         clickdot->line.y = -1;
276         clickdot->line.old_x = -1;
277         clickdot->line.old_y = -1;
278         clickdot->reset = 0;
279
280         return clickdot;
281 }
282
283 static void
284 clickdot_destroy(struct clickdot *clickdot)
285 {
286         if (clickdot->buffer)
287                 cairo_surface_destroy(clickdot->buffer);
288         widget_destroy(clickdot->widget);
289         window_destroy(clickdot->window);
290         free(clickdot);
291 }
292
293 int
294 main(int argc, char *argv[])
295 {
296         struct display *display;
297         struct clickdot *clickdot;
298
299         display = display_create(argc, argv);
300         if (display == NULL) {
301                 fprintf(stderr, "failed to create display: %m\n");
302                 return -1;
303         }
304
305         clickdot = clickdot_create(display);
306
307         display_run(display);
308
309         clickdot_destroy(clickdot);
310         display_destroy(display);
311
312         return 0;
313 }