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