toytoolkit: Don't draw shadows for maximized windows.
[profile/ivi/weston.git] / clients / view.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  * Copyright © 2009 Chris Wilson
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 <fcntl.h>
29 #include <unistd.h>
30 #include <math.h>
31 #include <time.h>
32 #include <cairo.h>
33 #include <glib.h>
34 #include <gio/gio.h>
35 #include <linux/input.h>
36
37 #include <glib/poppler-document.h>
38 #include <glib/poppler-page.h>
39
40 #include <wayland-client.h>
41
42 #include "window.h"
43
44 struct view {
45         struct window *window;
46         struct widget *widget;
47         struct display *display;
48
49         PopplerDocument *document;
50         int page;
51         int fullscreen;
52         int *view_counter;
53 };
54
55 static void
56 redraw_handler(struct widget *widget, void *data)
57 {
58         struct view *view = data;
59
60         struct rectangle allocation;
61         cairo_surface_t *surface;
62         cairo_t *cr;
63         PopplerPage *page;
64         double width, height, doc_aspect, window_aspect, scale;
65
66         widget_get_allocation(view->widget, &allocation);
67
68         surface = window_get_surface(view->window);
69
70         cr = cairo_create(surface);
71         cairo_rectangle(cr, allocation.x, allocation.y,
72                          allocation.width, allocation.height);
73         cairo_clip(cr);
74
75         cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
76         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
77         cairo_paint(cr);
78
79         if(!view->document) {
80                 cairo_destroy(cr);
81                 cairo_surface_destroy(surface);
82                 return;
83         }
84
85         page = poppler_document_get_page(view->document, view->page);
86         poppler_page_get_size(page, &width, &height);
87         doc_aspect = width / height;
88         window_aspect = (double) allocation.width / allocation.height;
89         if (doc_aspect < window_aspect)
90                 scale = allocation.height / height;
91         else
92                 scale = allocation.width / width;
93         cairo_translate(cr, allocation.x, allocation.y);
94         cairo_scale(cr, scale, scale);
95         cairo_translate(cr,
96                         (allocation.width - width * scale) / 2 / scale,
97                         (allocation.height - height * scale) / 2 / scale);
98         cairo_rectangle(cr, 0, 0, width, height);
99         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
100         cairo_set_source_rgb(cr, 1, 1, 1);
101         cairo_fill(cr);
102         poppler_page_render(page, cr);
103         cairo_destroy(cr);
104         cairo_surface_destroy(surface);
105         g_object_unref(G_OBJECT(page));
106 }
107
108 static void
109 resize_handler(struct widget *widget,
110                int32_t width, int32_t height, void *data)
111 {
112         struct view *view = data;
113
114         widget_set_size(view->widget, width, height);
115 }
116
117 static void
118 view_page_up(struct view *view)
119 {
120         if(view->page <= 0)
121                 return;
122
123         view->page--;
124         window_schedule_redraw(view->window);
125 }
126
127 static void
128 view_page_down(struct view *view)
129 {
130         if(!view->document ||
131            view->page >= poppler_document_get_n_pages(view->document) - 1) {
132                 return;
133         }
134
135         view->page++;
136         window_schedule_redraw(view->window);
137 }
138
139 static void
140 button_handler(struct widget *widget, struct input *input, uint32_t time,
141                uint32_t button, enum wl_pointer_button_state state,
142                void *data)
143 {
144         struct view *view = data;
145
146         if (state == WL_POINTER_BUTTON_STATE_RELEASED)
147                 return;
148
149         switch(button) {
150         case 275:
151                 view_page_up(view);
152                 break;
153         case 276:
154                 view_page_down(view);
155                 break;
156         default:
157                 break;
158         }
159 }
160
161 static void
162 fullscreen_handler(struct window *window, void *data)
163 {
164         struct view *view = data;
165
166         view->fullscreen ^= 1;
167         window_set_fullscreen(window, view->fullscreen);
168 }
169
170 static void
171 close_handler(struct window *window, void *data)
172 {
173         struct view *view = data;
174
175         *view->view_counter -= 1;
176         if (*view->view_counter == 0)
177                 display_exit(view->display);
178
179         widget_destroy(view->widget);
180         window_destroy(view->window);
181         if (view->document)
182                 g_object_unref(view->document);
183
184         free(view);
185 }
186
187 static void
188 key_handler(struct window *window, struct input *input, uint32_t time,
189             uint32_t key, uint32_t unicode,
190             enum wl_keyboard_key_state state, void *data)
191 {
192         struct view *view = data;
193
194         if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
195                 return;
196
197         switch (key) {
198         case KEY_SPACE:
199         case KEY_PAGEDOWN:
200         case KEY_RIGHT:
201         case KEY_DOWN:
202                 view_page_down(view);
203                 break;
204         case KEY_BACKSPACE:
205         case KEY_PAGEUP:
206         case KEY_LEFT:
207         case KEY_UP:
208                 view_page_up(view);
209                 break;
210         default:
211                 break;
212         }
213 }
214
215 static void
216 keyboard_focus_handler(struct window *window,
217                        struct input *device, void *data)
218 {
219         struct view *view = data;
220         window_schedule_redraw(view->window);
221 }
222
223 static struct view *
224 view_create(struct display *display,
225             uint32_t key, const char *filename, int fullscreen, int *view_counter)
226 {
227         struct view *view;
228         gchar *basename;
229         gchar *title;
230         GFile *file = NULL;
231         GError *error = NULL;
232
233         view = malloc(sizeof *view);
234         if (view == NULL)
235                 return view;
236         memset(view, 0, sizeof *view);
237
238         file = g_file_new_for_commandline_arg(filename);
239         basename = g_file_get_basename(file);
240         if(!basename) {
241                 title = g_strdup("Wayland View");
242         } else {
243                 title = g_strdup_printf("Wayland View - %s", basename);
244                 g_free(basename);
245         }
246
247         view->document = poppler_document_new_from_file(g_file_get_uri(file),
248                                                         NULL, &error);
249
250         if(error) {
251                 title = g_strdup("File not found");
252         }
253
254         view->window = window_create(display);
255         view->widget = frame_create(view->window, view);
256         window_set_title(view->window, title);
257         g_free(title);
258         view->display = display;
259
260         window_set_user_data(view->window, view);
261         window_set_key_handler(view->window, key_handler);
262         window_set_keyboard_focus_handler(view->window,
263                                           keyboard_focus_handler);
264         window_set_fullscreen_handler(view->window, fullscreen_handler);
265         window_set_close_handler(view->window, close_handler);
266
267         widget_set_button_handler(view->widget, button_handler);
268         widget_set_resize_handler(view->widget, resize_handler);
269         widget_set_redraw_handler(view->widget, redraw_handler);
270
271         view->page = 0;
272
273         view->fullscreen = fullscreen;
274         window_set_fullscreen(view->window, view->fullscreen);
275
276         window_schedule_resize(view->window, 500, 400);
277         view->view_counter = view_counter;
278         *view_counter += 1;
279
280         return view;
281 }
282
283 static int option_fullscreen;
284
285 static const struct weston_option view_options[] = {
286         { WESTON_OPTION_BOOLEAN, "fullscreen", 0, &option_fullscreen },
287 };
288
289 int
290 main(int argc, char *argv[])
291 {
292         struct display *d;
293         int i;
294         int view_counter = 0;
295
296         g_type_init();
297
298         argc = parse_options(view_options,
299                              ARRAY_LENGTH(view_options), argc, argv);
300
301         d = display_create(argc, argv);
302         if (d == NULL) {
303                 fprintf(stderr, "failed to create display: %m\n");
304                 return -1;
305         }
306
307         for (i = 1; i < argc; i++)
308                 view_create (d, i, argv[i], option_fullscreen, &view_counter);
309
310         if (view_counter > 0)
311                 display_run(d);
312
313         return 0;
314 }