blob: 6736826985a0509682b1a8244525172100c7ce44 [file] [log] [blame]
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -04001/*
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>
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040033#include <glib.h>
Eugeni Dodonov397b9082011-10-24 13:49:38 -020034#include <gio/gio.h>
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040035#include <linux/input.h>
36
37#include <glib/poppler-document.h>
38#include <glib/poppler-page.h>
39
Pekka Paalanen50719bc2011-11-22 14:18:50 +020040#include <wayland-client.h>
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040041
42#include "window.h"
43
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040044struct view {
45 struct window *window;
Kristian Høgsbergab5dacd2012-01-12 10:48:51 -050046 struct widget *widget;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040047 struct display *display;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040048
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040049 PopplerDocument *document;
50 int page;
51 int fullscreen;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040052};
53
54static void
Kristian Høgsbergab5dacd2012-01-12 10:48:51 -050055redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040056{
Kristian Høgsbergab5dacd2012-01-12 10:48:51 -050057 struct view *view = data;
58
Kristian Høgsbergda846ca2011-01-11 10:00:52 -050059 struct rectangle allocation;
Kristian Høgsberg09531622010-06-14 23:22:15 -040060 cairo_surface_t *surface;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040061 cairo_t *cr;
62 PopplerPage *page;
63 double width, height, doc_aspect, window_aspect, scale;
64
Kristian Høgsbergb3bef622011-05-13 13:52:18 -040065 if (view->fullscreen)
66 window_set_transparent(view->window, 0);
67 else
68 window_set_transparent(view->window, 1);
69
Kristian Høgsbergbb977002012-01-10 19:11:42 -050070 widget_get_allocation(view->widget, &allocation);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040071
Kristian Høgsberg09531622010-06-14 23:22:15 -040072 surface = window_get_surface(view->window);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040073
Kristian Høgsberg09531622010-06-14 23:22:15 -040074 cr = cairo_create(surface);
Kristian Høgsbergda846ca2011-01-11 10:00:52 -050075 cairo_rectangle(cr, allocation.x, allocation.y,
76 allocation.width, allocation.height);
Kristian Høgsberg09531622010-06-14 23:22:15 -040077 cairo_clip(cr);
78
Tim Wiederhake6685ace2011-01-25 22:21:59 +010079 cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040080 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
81 cairo_paint(cr);
Tim Wiederhake6685ace2011-01-25 22:21:59 +010082
83 if(!view->document) {
84 cairo_destroy(cr);
85 cairo_surface_destroy(surface);
86 window_flush(view->window);
87 return;
88 }
89
90 page = poppler_document_get_page(view->document, view->page);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040091 poppler_page_get_size(page, &width, &height);
92 doc_aspect = width / height;
Kristian Høgsbergda846ca2011-01-11 10:00:52 -050093 window_aspect = (double) allocation.width / allocation.height;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040094 if (doc_aspect < window_aspect)
Kristian Høgsbergda846ca2011-01-11 10:00:52 -050095 scale = allocation.height / height;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040096 else
Kristian Høgsbergda846ca2011-01-11 10:00:52 -050097 scale = allocation.width / width;
98 cairo_translate(cr, allocation.x, allocation.y);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040099 cairo_scale(cr, scale, scale);
100 cairo_translate(cr,
Kristian Høgsbergda846ca2011-01-11 10:00:52 -0500101 (allocation.width - width * scale) / 2 / scale,
102 (allocation.height - height * scale) / 2 / scale);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400103 cairo_rectangle(cr, 0, 0, width, height);
104 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
105 cairo_set_source_rgb(cr, 1, 1, 1);
106 cairo_fill(cr);
107 poppler_page_render(page, cr);
108 cairo_destroy(cr);
Tim Wiederhake80bf6f72011-01-25 22:22:00 +0100109 cairo_surface_destroy(surface);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400110 g_object_unref(G_OBJECT(page));
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400111}
112
113static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500114resize_handler(struct widget *widget,
Kristian Høgsberg12283cc2011-05-13 13:51:13 -0400115 int32_t width, int32_t height, void *data)
116{
117 struct view *view = data;
118
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500119 widget_set_size(view->widget, width, height);
Kristian Høgsberg12283cc2011-05-13 13:51:13 -0400120}
121
122static void
Tim Wiederhake655467a2011-01-25 22:21:57 +0100123view_page_up(struct view *view)
124{
125 if(view->page <= 0)
126 return;
127
128 view->page--;
129 window_schedule_redraw(view->window);
130}
131
132static void
133view_page_down(struct view *view)
134{
Tim Wiederhake6685ace2011-01-25 22:21:59 +0100135 if(!view->document ||
136 view->page >= poppler_document_get_n_pages(view->document) - 1) {
Tim Wiederhake655467a2011-01-25 22:21:57 +0100137 return;
Tim Wiederhake6685ace2011-01-25 22:21:59 +0100138 }
Tim Wiederhake655467a2011-01-25 22:21:57 +0100139
140 view->page++;
141 window_schedule_redraw(view->window);
142}
143
144static void
Kristian Høgsbergab5dacd2012-01-12 10:48:51 -0500145button_handler(struct widget *widget, struct input *input, uint32_t time,
Tim Wiederhake655467a2011-01-25 22:21:57 +0100146 int button, int state, void *data)
147{
Kristian Høgsbergab5dacd2012-01-12 10:48:51 -0500148 struct view *view = data;
Tim Wiederhake655467a2011-01-25 22:21:57 +0100149
150 if(!state)
151 return;
152
153 switch(button) {
154 case 275:
155 view_page_up(view);
156 break;
157 case 276:
158 view_page_down(view);
159 break;
160 default:
161 break;
162 }
163}
164
165static void
Kristian Høgsberg67cac8a2011-01-19 14:20:33 -0500166key_handler(struct window *window, struct input *input, uint32_t time,
167 uint32_t key, uint32_t unicode, uint32_t state, void *data)
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400168{
169 struct view *view = data;
170
Tim Wiederhake655467a2011-01-25 22:21:57 +0100171 if(!state)
172 return;
173
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400174 switch (key) {
175 case KEY_F11:
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400176 view->fullscreen ^= 1;
177 window_set_fullscreen(window, view->fullscreen);
Kristian Høgsberg80d746f2010-06-14 23:52:50 -0400178 window_schedule_redraw(view->window);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400179 break;
180 case KEY_SPACE:
181 case KEY_PAGEDOWN:
Tim Wiederhake655467a2011-01-25 22:21:57 +0100182 case KEY_RIGHT:
183 case KEY_DOWN:
184 view_page_down(view);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400185 break;
186 case KEY_BACKSPACE:
187 case KEY_PAGEUP:
Tim Wiederhake655467a2011-01-25 22:21:57 +0100188 case KEY_LEFT:
189 case KEY_UP:
190 view_page_up(view);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400191 break;
192 default:
193 break;
194 }
195}
196
197static void
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400198keyboard_focus_handler(struct window *window,
Kristian Høgsberg43788b12010-07-28 23:50:12 -0400199 struct input *device, void *data)
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400200{
201 struct view *view = data;
Kristian Høgsberg80d746f2010-06-14 23:52:50 -0400202 window_schedule_redraw(view->window);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400203}
204
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400205static struct view *
Kristian Høgsberg393d47a2011-05-13 13:54:19 -0400206view_create(struct display *display,
207 uint32_t key, const char *filename, int fullscreen)
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400208{
209 struct view *view;
210 gchar *basename;
211 gchar *title;
Tim Wiederhake9aad08e2011-01-25 22:21:58 +0100212 GFile *file = NULL;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400213 GError *error = NULL;
214
215 view = malloc(sizeof *view);
216 if (view == NULL)
217 return view;
218 memset(view, 0, sizeof *view);
219
Tim Wiederhake9aad08e2011-01-25 22:21:58 +0100220 file = g_file_new_for_commandline_arg(filename);
221 basename = g_file_get_basename(file);
222 if(!basename) {
223 title = "Wayland View";
224 } else {
225 title = g_strdup_printf("Wayland View - %s", basename);
226 g_free(basename);
227 }
228
229 view->document = poppler_document_new_from_file(g_file_get_uri(file),
230 NULL, &error);
231
232 if(error) {
233 title = "File not found";
Tim Wiederhake9aad08e2011-01-25 22:21:58 +0100234 }
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400235
Kristian Høgsberg248c1b62011-01-21 18:03:15 -0500236 view->window = window_create(display, 500, 400);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500237 view->widget = frame_create(view->window, view);
Kristian Høgsberg248c1b62011-01-21 18:03:15 -0500238 window_set_title(view->window, title);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400239 view->display = display;
240
Kristian Høgsbergc8c37342010-06-25 11:19:22 -0400241 window_set_user_data(view->window, view);
Kristian Høgsbergc8c37342010-06-25 11:19:22 -0400242 window_set_key_handler(view->window, key_handler);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400243 window_set_keyboard_focus_handler(view->window,
Kristian Høgsbergc8c37342010-06-25 11:19:22 -0400244 keyboard_focus_handler);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500245 widget_set_button_handler(view->widget, button_handler);
246 widget_set_resize_handler(view->widget, resize_handler);
247 widget_set_redraw_handler(view->widget, redraw_handler);
248
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400249 view->page = 0;
Kristian Høgsberg393d47a2011-05-13 13:54:19 -0400250
251 view->fullscreen = fullscreen;
252 window_set_fullscreen(view->window, view->fullscreen);
253
Kristian Høgsbergab5dacd2012-01-12 10:48:51 -0500254 window_schedule_resize(view->window, 500, 400);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400255
256 return view;
257}
258
Kristian Høgsberg393d47a2011-05-13 13:54:19 -0400259static int option_fullscreen;
260
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400261static const GOptionEntry option_entries[] = {
Kristian Høgsberg393d47a2011-05-13 13:54:19 -0400262 { "fullscreen", 'f', 0, G_OPTION_ARG_NONE,
263 &option_fullscreen, "Run in fullscreen mode" },
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400264 { NULL }
265};
266
267int
268main(int argc, char *argv[])
269{
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400270 struct display *d;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400271 int i;
272
Benjamin Franzke4b87a132011-09-01 10:36:16 +0200273 d = display_create(&argc, &argv, option_entries);
Yuval Fledele9f5e362010-11-22 21:34:19 +0200274 if (d == NULL) {
275 fprintf(stderr, "failed to create display: %m\n");
276 return -1;
277 }
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400278
Kristian Høgsberg00439612011-01-25 15:16:01 -0500279 for (i = 1; i < argc; i++)
Kristian Høgsberg393d47a2011-05-13 13:54:19 -0400280 view_create (d, i, argv[i], option_fullscreen);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400281
Kristian Høgsberg7824d812010-06-08 14:59:44 -0400282 display_run(d);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400283
284 return 0;
285}