blob: b9d348b173ba5356acc77229aa11299889543e3d [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>
33#include <cairo-drm.h>
34#include <glib.h>
35#include <linux/input.h>
36
37#include <glib/poppler-document.h>
38#include <glib/poppler-page.h>
39
40#include "wayland-util.h"
41#include "wayland-client.h"
42#include "wayland-glib.h"
43
44#include "window.h"
45
46static const char gem_device[] = "/dev/dri/card0";
47static const char socket_name[] = "\0wayland";
48
49struct view {
50 struct window *window;
51 struct display *display;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040052 uint32_t key;
53
54 gboolean redraw_scheduled;
55 gboolean redraw_pending;
56
57 cairo_surface_t *surface;
58 gchar *filename;
59 PopplerDocument *document;
60 int page;
61 int fullscreen;
62 int focused;
63};
64
65static void
66view_draw(struct view *view)
67{
68 struct rectangle rectangle;
69 cairo_t *cr;
70 PopplerPage *page;
71 double width, height, doc_aspect, window_aspect, scale;
72
73 view->redraw_pending = 0;
74
75 window_draw(view->window);
76
77 window_get_child_rectangle(view->window, &rectangle);
78
79 page = poppler_document_get_page(view->document, view->page);
80
81 view->surface =
82 window_create_surface(view->window, &rectangle);
83
84 cr = cairo_create(view->surface);
85 cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
86 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
87 cairo_paint(cr);
88 poppler_page_get_size(page, &width, &height);
89 doc_aspect = width / height;
90 window_aspect = (double) rectangle.width / rectangle.height;
91 if (doc_aspect < window_aspect)
92 scale = rectangle.height / height;
93 else
94 scale = rectangle.width / width;
95 cairo_scale(cr, scale, scale);
96 cairo_translate(cr,
97 (rectangle.width - width * scale) / 2 / scale,
98 (rectangle.height - height * scale) / 2 / scale);
99 cairo_rectangle(cr, 0, 0, width, height);
100 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
101 cairo_set_source_rgb(cr, 1, 1, 1);
102 cairo_fill(cr);
103 poppler_page_render(page, cr);
104 cairo_destroy(cr);
105 g_object_unref(G_OBJECT(page));
106
107 window_copy_surface(view->window,
108 &rectangle,
109 view->surface);
110
Kristian Høgsberg478d9262010-06-08 20:34:11 -0400111 window_commit(view->window, 0);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400112}
113
114static gboolean
115view_idle_redraw(void *data)
116{
117 struct view *view = data;
118
119 view_draw(view);
120
121 return FALSE;
122}
123
124static void
125view_schedule_redraw(struct view *view)
126{
127 if (!view->redraw_scheduled) {
128 view->redraw_scheduled = 1;
129 g_idle_add(view_idle_redraw, view);
130 } else {
131 view->redraw_pending = 1;
132 }
133}
134
135static void
136key_handler(struct window *window, uint32_t key, uint32_t unicode,
137 uint32_t state, uint32_t modifiers, void *data)
138{
139 struct view *view = data;
140
141 switch (key) {
142 case KEY_F11:
143 if (!state)
144 break;
145 view->fullscreen ^= 1;
146 window_set_fullscreen(window, view->fullscreen);
147 view_schedule_redraw(view);
148 break;
149 case KEY_SPACE:
150 case KEY_PAGEDOWN:
151 if (!state)
152 break;
153 view->page++;
154 view_schedule_redraw(view);
155 break;
156 case KEY_BACKSPACE:
157 case KEY_PAGEUP:
158 if (!state)
159 break;
160 view->page--;
161 view_schedule_redraw(view);
162 break;
163 default:
164 break;
165 }
166}
167
168static void
169resize_handler(struct window *window, void *data)
170{
171 struct view *view = data;
172
173 view_schedule_redraw(view);
174}
175
176static void
Kristian Høgsberg478d9262010-06-08 20:34:11 -0400177acknowledge_handler(struct window *window,
178 uint32_t key, uint32_t frame, void *data)
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400179{
180 struct view *view = data;
181
182 if (view->key != key)
183 return;
184
185 cairo_surface_destroy(view->surface);
186 view->redraw_scheduled = 0;
187 if (view->redraw_pending) {
188 view->redraw_pending = 0;
189 view_schedule_redraw(view);
190 }
191}
192
193static void
194keyboard_focus_handler(struct window *window,
195 struct wl_input_device *device, void *data)
196{
197 struct view *view = data;
198
199 view->focused = (device != NULL);
200 view_schedule_redraw(view);
201}
202
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400203static struct view *
204view_create(struct display *display, uint32_t key, const char *filename)
205{
206 struct view *view;
207 gchar *basename;
208 gchar *title;
209 GError *error = NULL;
210
211 view = malloc(sizeof *view);
212 if (view == NULL)
213 return view;
214 memset(view, 0, sizeof *view);
215
216 basename = g_path_get_basename(filename);
217 title = g_strdup_printf("Wayland View - %s", basename);
218 g_free(basename);
219
220 view->filename = g_strdup(filename);
221
222 view->window = window_create(display, title,
223 100 * key, 100 * key, 500, 400);
224 view->display = display;
225
226 /* FIXME: Window uses key 1 for moves, need some kind of
227 * allocation scheme here. Or maybe just a real toolkit. */
228 view->key = key + 100;
229 view->redraw_scheduled = 1;
230
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400231 window_set_resize_handler(view->window, resize_handler, view);
232 window_set_key_handler(view->window, key_handler, view);
233 window_set_keyboard_focus_handler(view->window,
234 keyboard_focus_handler, view);
Kristian Høgsberg478d9262010-06-08 20:34:11 -0400235 window_set_acknowledge_handler(view->window, acknowledge_handler, view);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400236
237 view->document = poppler_document_new_from_file(view->filename,
238 NULL, &error);
239 view->page = 0;
240 view_draw(view);
241
242 return view;
243}
244
245static const GOptionEntry option_entries[] = {
246 { NULL }
247};
248
249int
250main(int argc, char *argv[])
251{
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400252 struct display *d;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400253 int i;
254
Kristian Høgsberg7824d812010-06-08 14:59:44 -0400255 d = display_create(&argc, &argv, option_entries);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400256
257 for (i = 1; i < argc; i++) {
258 struct view *view;
259
260 view = view_create (d, i, argv[i]);
261 }
262
Kristian Høgsberg7824d812010-06-08 14:59:44 -0400263 display_run(d);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400264
265 return 0;
266}