nested: Remove the surface from the surface list when destroyed
[profile/ivi/weston-ivi-shell.git] / clients / transformed.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  * Copyright © 2012 Intel Corporation
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting documentation, and
9  * that the name of the copyright holders not be used in advertising or
10  * publicity pertaining to distribution of the software without specific,
11  * written prior permission.  The copyright holders make no representations
12  * about the suitability of this software for any purpose.  It is provided "as
13  * is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21  * OF THIS SOFTWARE.
22  */
23
24 #include <stdint.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29 #include <cairo.h>
30
31 #include <linux/input.h>
32 #include <wayland-client.h>
33 #include "window.h"
34
35 struct transformed {
36         struct display *display;
37         struct window *window;
38         struct widget *widget;
39         int width, height;
40         int fullscreen;
41         enum wl_shell_surface_fullscreen_method fullscreen_method;
42 };
43
44 static void
45 draw_stuff(cairo_t *cr, int width, int height)
46 {
47         cairo_matrix_t m;
48         cairo_get_matrix (cr, &m);
49
50         cairo_translate(cr, width / 2, height / 2);
51         cairo_scale(cr, width / 2, height / 2);
52
53         cairo_set_source_rgba(cr, 0, 0, 0.3, 1.0);
54         cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
55         cairo_rectangle(cr, -1, -1, 2, 2);
56         cairo_fill(cr);
57
58         cairo_set_source_rgb(cr, 1, 0, 0);
59         cairo_move_to(cr, 0,  0);
60         cairo_line_to(cr, 0, -1);
61
62         cairo_save(cr);
63         cairo_set_matrix(cr, &m);
64         cairo_set_line_width(cr, 2.0);
65         cairo_stroke(cr);
66         cairo_restore(cr);
67
68         cairo_set_source_rgb(cr, 0, 1, 0);
69         cairo_move_to(cr, 0, 0);
70         cairo_line_to(cr, 1, 0);
71
72         cairo_save(cr);
73         cairo_set_matrix(cr, &m);
74         cairo_set_line_width(cr, 2.0);
75         cairo_stroke(cr);
76         cairo_restore(cr);
77
78         cairo_set_source_rgb(cr, 1, 1, 1);
79         cairo_move_to(cr, 0, 0);
80         cairo_line_to(cr, 0, 1);
81         cairo_move_to(cr,  0, 0);
82         cairo_line_to(cr, -1, 0);
83
84         cairo_save(cr);
85         cairo_set_matrix(cr, &m);
86         cairo_set_line_width(cr, 2.0);
87         cairo_stroke(cr);
88         cairo_restore(cr);
89
90         cairo_destroy(cr);
91 }
92
93 static void
94 fullscreen_handler(struct window *window, void *data)
95 {
96         struct transformed *transformed = data;
97
98         transformed->fullscreen ^= 1;
99         window_set_fullscreen(window, transformed->fullscreen);
100 }
101
102 static void
103 resize_handler(struct widget *widget, int width, int height, void *data)
104 {
105         struct transformed *transformed = data;
106
107         if (transformed->fullscreen_method !=
108             WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT)
109                 widget_set_size(widget, transformed->width, transformed->height);
110 }
111
112 static void
113 redraw_handler(struct widget *widget, void *data)
114 {
115         struct transformed *transformed = data;
116         struct rectangle allocation;
117         cairo_surface_t *surface;
118         cairo_t *cr;
119
120         surface = window_get_surface(transformed->window);
121         if (surface == NULL ||
122             cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
123                 fprintf(stderr, "failed to create cairo egl surface\n");
124                 return;
125         }
126
127         widget_get_allocation(transformed->widget, &allocation);
128
129         cr = widget_cairo_create(widget);
130         draw_stuff(cr, allocation.width, allocation.height);
131
132         cairo_surface_destroy(surface);
133 }
134
135 static void
136 output_handler(struct window *window, struct output *output, int enter,
137                void *data)
138 {
139         if (!enter)
140                 return;
141
142         window_set_buffer_transform(window, output_get_transform(output));
143         window_set_buffer_scale(window, output_get_scale(output));
144         window_schedule_redraw(window);
145 }
146
147 static void
148 key_handler(struct window *window, struct input *input, uint32_t time,
149             uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
150             void *data)
151 {
152         int transform, scale;
153
154         if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
155                 return;
156
157         transform = window_get_buffer_transform (window);
158         scale = window_get_buffer_scale (window);
159         switch (sym) {
160         case XKB_KEY_Left:
161                 if (transform == 0)
162                         transform = 3;
163                 else if (transform == 4)
164                         transform = 7;
165                 else
166                         transform--;
167                 break;
168
169         case XKB_KEY_Right:
170                 if (transform == 3)
171                         transform = 0;
172                 else if (transform == 7)
173                         transform = 4;
174                 else
175                         transform++;
176                 break;
177
178         case XKB_KEY_space:
179                 if (transform >= 4)
180                         transform -= 4;
181                 else
182                         transform += 4;
183                 break;
184
185         case XKB_KEY_z:
186                 if (scale == 1)
187                         scale = 2;
188                 else
189                         scale = 1;
190                 break;
191         }
192
193         printf ("setting buffer transform to %d\n", transform);
194         printf ("setting buffer scale to %d\n", scale);
195         window_set_buffer_transform(window, transform);
196         window_set_buffer_scale(window, scale);
197         window_schedule_redraw(window);
198 }
199
200 static void
201 button_handler(struct widget *widget,
202                struct input *input, uint32_t time,
203                uint32_t button, enum wl_pointer_button_state state, void *data)
204 {
205         struct transformed *transformed = data;
206
207         switch (button) {
208         case BTN_LEFT:
209                 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
210                         window_move(transformed->window, input,
211                                     display_get_serial(transformed->display));
212                 break;
213         case BTN_MIDDLE:
214                 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
215                         widget_schedule_redraw(widget);
216                 break;
217         case BTN_RIGHT:
218                 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
219                         window_show_frame_menu(transformed->window, input, time);
220                 break;
221         }
222 }
223
224 static void
225 touch_handler(struct widget *widget, struct input *input, 
226                    uint32_t serial, uint32_t time, int32_t id, 
227                    float x, float y, void *data)
228 {
229         struct transformed *transformed = data;
230         window_move(transformed->window, input, display_get_serial(transformed->display));
231 }
232
233 static void
234 usage(int error_code)
235 {
236         fprintf(stderr, "Usage: transformed [OPTIONS]\n\n"
237                 "   -d\t\tUse \"driver\" fullscreen method\n"
238                 "   -w <width>\tSet window width to <width>\n"
239                 "   -h <height>\tSet window height to <height>\n"
240                 "   --help\tShow this help text\n\n");
241
242         exit(error_code);
243 }
244
245 int main(int argc, char *argv[])
246 {
247         struct transformed transformed;
248         struct display *d;
249         int i;
250
251         transformed.width = 500;
252         transformed.height = 250;
253         transformed.fullscreen = 0;
254         transformed.fullscreen_method =
255                 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
256
257         for (i = 1; i < argc; i++) {
258                 if (strcmp(argv[i], "-d") == 0) {
259                         transformed.fullscreen_method =
260                                 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER;
261                 } else if (strcmp(argv[i], "-w") == 0) {
262                         if (++i >= argc)
263                                 usage(EXIT_FAILURE);
264
265                         transformed.width = atol(argv[i]);
266                 } else if (strcmp(argv[i], "-h") == 0) {
267                         if (++i >= argc)
268                                 usage(EXIT_FAILURE);
269
270                         transformed.height = atol(argv[i]);
271                 } else if (strcmp(argv[i], "--help") == 0)
272                         usage(EXIT_SUCCESS);
273                 else
274                         usage(EXIT_FAILURE);
275         }
276
277         d = display_create(&argc, argv);
278         if (d == NULL) {
279                 fprintf(stderr, "failed to create display: %m\n");
280                 return -1;
281         }
282
283         transformed.display = d;
284         transformed.window = window_create(d);
285         transformed.widget =
286                 window_add_widget(transformed.window, &transformed);
287
288         window_set_title(transformed.window, "Transformed");
289         window_set_fullscreen_method(transformed.window,
290                                      transformed.fullscreen_method);
291
292         widget_set_transparent(transformed.widget, 0);
293         widget_set_default_cursor(transformed.widget, CURSOR_BLANK);
294
295         widget_set_resize_handler(transformed.widget, resize_handler);
296         widget_set_redraw_handler(transformed.widget, redraw_handler);
297         widget_set_button_handler(transformed.widget, button_handler);
298
299         widget_set_touch_down_handler(transformed.widget, touch_handler);
300
301         window_set_key_handler(transformed.window, key_handler);
302         window_set_fullscreen_handler(transformed.window, fullscreen_handler);
303         window_set_output_handler(transformed.window, output_handler);
304
305         window_set_user_data(transformed.window, &transformed);
306         window_schedule_resize(transformed.window,
307                                transformed.width, transformed.height);
308
309         display_run(d);
310
311         return 0;
312 }