nested: Remove the surface from the surface list when destroyed
[profile/ivi/weston-ivi-shell.git] / clients / fullscreen.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 <stdarg.h>
28 #include <string.h>
29 #include <math.h>
30 #include <cairo.h>
31
32 #include <linux/input.h>
33 #include <wayland-client.h>
34 #include "window.h"
35
36 struct fullscreen {
37         struct display *display;
38         struct window *window;
39         struct widget *widget;
40         int width, height;
41         int fullscreen;
42         float pointer_x, pointer_y;
43         enum wl_shell_surface_fullscreen_method fullscreen_method;
44 };
45
46 static void
47 fullscreen_handler(struct window *window, void *data)
48 {
49         struct fullscreen *fullscreen = data;
50
51         fullscreen->fullscreen ^= 1;
52         window_set_fullscreen(window, fullscreen->fullscreen);
53 }
54
55 static void
56 resize_handler(struct widget *widget, int width, int height, void *data)
57 {
58         struct fullscreen *fullscreen = data;
59
60         widget_set_size(widget, fullscreen->width, fullscreen->height);
61 }
62
63 static void
64 draw_string(cairo_t *cr,
65             const char *fmt, ...)
66 {
67         char buffer[4096];
68         char *p, *end;
69         va_list argp;
70         cairo_text_extents_t text_extents;
71         cairo_font_extents_t font_extents;
72
73         cairo_save(cr);
74
75         cairo_select_font_face(cr, "sans",
76                                CAIRO_FONT_SLANT_NORMAL,
77                                CAIRO_FONT_WEIGHT_NORMAL);
78         cairo_set_font_size(cr, 14);
79
80         cairo_font_extents (cr, &font_extents);
81
82         va_start(argp, fmt);
83
84         vsnprintf(buffer, sizeof(buffer), fmt, argp);
85
86         p = buffer;
87         while (*p) {
88                 end = strchr(p, '\n');
89                 if (end)
90                         *end = 0;
91
92                 cairo_show_text(cr, p);
93                 cairo_text_extents (cr, p, &text_extents);
94                 cairo_rel_move_to (cr, -text_extents.x_advance, font_extents.height);
95
96                 if (end)
97                         p = end + 1;
98                 else
99                         break;
100         }
101
102         va_end(argp);
103
104         cairo_restore(cr);
105
106 }
107
108 static void
109 redraw_handler(struct widget *widget, void *data)
110 {
111         struct fullscreen *fullscreen = data;
112         struct rectangle allocation;
113         cairo_surface_t *surface;
114         cairo_t *cr;
115         int i;
116         double x, y, border;
117         const char *method_name[] = { "default", "scale", "driver", "fill" };
118
119         surface = window_get_surface(fullscreen->window);
120         if (surface == NULL ||
121             cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
122                 fprintf(stderr, "failed to create cairo egl surface\n");
123                 return;
124         }
125
126         widget_get_allocation(fullscreen->widget, &allocation);
127
128         cr = widget_cairo_create(widget);
129
130         cairo_set_source_rgb(cr, 0, 0, 0);
131         cairo_paint (cr);
132
133         cairo_set_source_rgb(cr, 0, 0, 1);
134         cairo_set_line_width (cr, 10);
135         cairo_rectangle(cr, 5, 5, allocation.width - 10, allocation.height - 10);
136         cairo_stroke (cr);
137
138         cairo_move_to(cr,
139                       allocation.x + 15,
140                       allocation.y + 25);
141         cairo_set_source_rgb(cr, 1, 1, 1);
142
143         draw_string(cr,
144                     "Surface size: %d, %d\n"
145                     "Scale: %d, transform: %d\n"
146                     "Pointer: %f,%f\n"
147                     "Fullscreen: %d, method: %s\n"
148                     "Keys: (s)cale, (t)ransform, si(z)e, (m)ethod, (f)ullscreen, (q)uit\n",
149                     fullscreen->width, fullscreen->height,
150                     window_get_buffer_scale (fullscreen->window),
151                     window_get_buffer_transform (fullscreen->window),
152                     fullscreen->pointer_x, fullscreen->pointer_y,
153                     fullscreen->fullscreen, method_name[fullscreen->fullscreen_method]);
154
155         y = 100;
156         i = 0;
157         while (y + 60 < fullscreen->height) {
158                 border = (i++ % 2 == 0) ? 1 : 0.5;
159
160                 x = 50;
161                 cairo_set_line_width (cr, border);
162                 while (x + 70 < fullscreen->width) {
163                         if (fullscreen->pointer_x >= x && fullscreen->pointer_x < x + 50 &&
164                             fullscreen->pointer_y >= y && fullscreen->pointer_y < y + 40) {
165                                 cairo_set_source_rgb(cr, 1, 0, 0);
166                                 cairo_rectangle(cr,
167                                                 x, y,
168                                                 50, 40);
169                                 cairo_fill(cr);
170                         }
171                         cairo_set_source_rgb(cr, 0, 1, 0);
172                         cairo_rectangle(cr,
173                                         x + border/2.0, y + border/2.0,
174                                         50, 40);
175                         cairo_stroke(cr);
176                         x += 60;
177                 }
178
179                 y += 50;
180         }
181
182         cairo_destroy(cr);
183 }
184
185 static void
186 key_handler(struct window *window, struct input *input, uint32_t time,
187             uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
188             void *data)
189 {
190         struct fullscreen *fullscreen = data;
191         int transform, scale;
192         static int current_size = 0;
193         int widths[] = { 640, 320, 800, 400 };
194         int heights[] = { 480, 240, 600, 300 };
195
196         if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
197                 return;
198
199         switch (sym) {
200         case XKB_KEY_t:
201                 transform = window_get_buffer_transform (window);
202                 transform = (transform + 1) % 8;
203                 window_set_buffer_transform(window, transform);
204                 window_schedule_redraw(window);
205                 break;
206
207         case XKB_KEY_s:
208                 scale = window_get_buffer_scale (window);
209                 if (scale == 1)
210                         scale = 2;
211                 else
212                         scale = 1;
213                 window_set_buffer_scale(window, scale);
214                 window_schedule_redraw(window);
215                 break;
216
217         case XKB_KEY_z:
218                 current_size = (current_size + 1) % 4;
219                 fullscreen->width = widths[current_size];
220                 fullscreen->height = heights[current_size];
221                 window_schedule_resize(fullscreen->window,
222                                        fullscreen->width, fullscreen->height);
223                 break;
224
225         case XKB_KEY_m:
226                 fullscreen->fullscreen_method = (fullscreen->fullscreen_method + 1) % 4;
227                 window_set_fullscreen_method(fullscreen->window,
228                                              fullscreen->fullscreen_method);
229                 window_schedule_redraw(window);
230                 break;
231
232         case XKB_KEY_f:
233                 fullscreen->fullscreen ^= 1;
234                 window_set_fullscreen(window, fullscreen->fullscreen);
235                 break;
236
237         case XKB_KEY_q:
238                 exit (0);
239                 break;
240         }
241 }
242
243 static int
244 motion_handler(struct widget *widget,
245                struct input *input,
246                uint32_t time,
247                float x,
248                float y, void *data)
249 {
250         struct fullscreen *fullscreen = data;
251
252         fullscreen->pointer_x = x;
253         fullscreen->pointer_y = y;
254
255         widget_schedule_redraw(widget);
256         return 0;
257 }
258
259
260 static void
261 button_handler(struct widget *widget,
262                struct input *input, uint32_t time,
263                uint32_t button, enum wl_pointer_button_state state, void *data)
264 {
265         struct fullscreen *fullscreen = data;
266
267         switch (button) {
268         case BTN_LEFT:
269                 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
270                         window_move(fullscreen->window, input,
271                                     display_get_serial(fullscreen->display));
272                 break;
273         case BTN_RIGHT:
274                 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
275                         window_show_frame_menu(fullscreen->window, input, time);
276                 break;
277         }
278 }
279
280 static void
281 touch_handler(struct widget *widget, struct input *input, 
282                    uint32_t serial, uint32_t time, int32_t id, 
283                    float x, float y, void *data)
284 {
285         struct fullscreen *fullscreen = data;
286         window_move(fullscreen->window, input, display_get_serial(fullscreen->display));
287 }
288
289 static void
290 usage(int error_code)
291 {
292         fprintf(stderr, "Usage: fullscreen [OPTIONS]\n\n"
293                 "   -w <width>\tSet window width to <width>\n"
294                 "   -h <height>\tSet window height to <height>\n"
295                 "   --help\tShow this help text\n\n");
296
297         exit(error_code);
298 }
299
300 int main(int argc, char *argv[])
301 {
302         struct fullscreen fullscreen;
303         struct display *d;
304         int i;
305
306         fullscreen.width = 640;
307         fullscreen.height = 480;
308         fullscreen.fullscreen = 0;
309         fullscreen.fullscreen_method =
310                 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
311
312         for (i = 1; i < argc; i++) {
313                 if (strcmp(argv[i], "-w") == 0) {
314                         if (++i >= argc)
315                                 usage(EXIT_FAILURE);
316
317                         fullscreen.width = atol(argv[i]);
318                 } else if (strcmp(argv[i], "-h") == 0) {
319                         if (++i >= argc)
320                                 usage(EXIT_FAILURE);
321
322                         fullscreen.height = atol(argv[i]);
323                 } else if (strcmp(argv[i], "--help") == 0)
324                         usage(EXIT_SUCCESS);
325                 else
326                         usage(EXIT_FAILURE);
327         }
328
329         d = display_create(&argc, argv);
330         if (d == NULL) {
331                 fprintf(stderr, "failed to create display: %m\n");
332                 return -1;
333         }
334
335         fullscreen.display = d;
336         fullscreen.window = window_create(d);
337         fullscreen.widget =
338                 window_add_widget(fullscreen.window, &fullscreen);
339
340         window_set_title(fullscreen.window, "Fullscreen");
341         window_set_fullscreen_method(fullscreen.window,
342                                      fullscreen.fullscreen_method);
343
344         widget_set_transparent(fullscreen.widget, 0);
345         widget_set_default_cursor(fullscreen.widget, CURSOR_LEFT_PTR);
346
347         widget_set_resize_handler(fullscreen.widget, resize_handler);
348         widget_set_redraw_handler(fullscreen.widget, redraw_handler);
349         widget_set_button_handler(fullscreen.widget, button_handler);
350         widget_set_motion_handler(fullscreen.widget, motion_handler);
351
352         widget_set_touch_down_handler(fullscreen.widget, touch_handler);
353
354         window_set_key_handler(fullscreen.window, key_handler);
355         window_set_fullscreen_handler(fullscreen.window, fullscreen_handler);
356
357         window_set_user_data(fullscreen.window, &fullscreen);
358         /* Hack to set minimum allocation so we can shrink later */
359         window_schedule_resize(fullscreen.window,
360                                1, 1);
361         window_schedule_resize(fullscreen.window,
362                                fullscreen.width, fullscreen.height);
363
364         display_run(d);
365
366         return 0;
367 }