blob: 4ef6b6c4632999e3d776ce5127ec8e01858359e7 [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
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040054 gchar *filename;
55 PopplerDocument *document;
56 int page;
57 int fullscreen;
58 int focused;
59};
60
61static void
62view_draw(struct view *view)
63{
64 struct rectangle rectangle;
Kristian Høgsberg09531622010-06-14 23:22:15 -040065 cairo_surface_t *surface;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040066 cairo_t *cr;
67 PopplerPage *page;
68 double width, height, doc_aspect, window_aspect, scale;
69
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040070 window_draw(view->window);
71
72 window_get_child_rectangle(view->window, &rectangle);
73
74 page = poppler_document_get_page(view->document, view->page);
75
Kristian Høgsberg09531622010-06-14 23:22:15 -040076 surface = window_get_surface(view->window);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040077
Kristian Høgsberg09531622010-06-14 23:22:15 -040078 cr = cairo_create(surface);
79 cairo_rectangle(cr, rectangle.x, rectangle.y,
80 rectangle.width, rectangle.height);
81 cairo_clip(cr);
82
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040083 cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
84 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
85 cairo_paint(cr);
86 poppler_page_get_size(page, &width, &height);
87 doc_aspect = width / height;
88 window_aspect = (double) rectangle.width / rectangle.height;
89 if (doc_aspect < window_aspect)
90 scale = rectangle.height / height;
91 else
92 scale = rectangle.width / width;
Kristian Høgsberg09531622010-06-14 23:22:15 -040093 cairo_translate(cr, rectangle.x, rectangle.y);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040094 cairo_scale(cr, scale, scale);
95 cairo_translate(cr,
96 (rectangle.width - width * scale) / 2 / scale,
97 (rectangle.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 g_object_unref(G_OBJECT(page));
105
Kristian Høgsberg478d9262010-06-08 20:34:11 -0400106 window_commit(view->window, 0);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400107}
108
Kristian Høgsberg80d746f2010-06-14 23:52:50 -0400109static void
110redraw_handler(struct window *window, void *data)
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400111{
112 struct view *view = data;
113
114 view_draw(view);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400115}
116
117static void
118key_handler(struct window *window, uint32_t key, uint32_t unicode,
119 uint32_t state, uint32_t modifiers, void *data)
120{
121 struct view *view = data;
122
123 switch (key) {
124 case KEY_F11:
125 if (!state)
126 break;
127 view->fullscreen ^= 1;
128 window_set_fullscreen(window, view->fullscreen);
Kristian Høgsberg80d746f2010-06-14 23:52:50 -0400129 window_schedule_redraw(view->window);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400130 break;
131 case KEY_SPACE:
132 case KEY_PAGEDOWN:
133 if (!state)
134 break;
135 view->page++;
Kristian Høgsberg80d746f2010-06-14 23:52:50 -0400136 window_schedule_redraw(view->window);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400137 break;
138 case KEY_BACKSPACE:
139 case KEY_PAGEUP:
140 if (!state)
141 break;
142 view->page--;
Kristian Høgsberg80d746f2010-06-14 23:52:50 -0400143 window_schedule_redraw(view->window);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400144 break;
145 default:
146 break;
147 }
148}
149
150static void
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400151keyboard_focus_handler(struct window *window,
152 struct wl_input_device *device, void *data)
153{
154 struct view *view = data;
155
156 view->focused = (device != NULL);
Kristian Høgsberg80d746f2010-06-14 23:52:50 -0400157 window_schedule_redraw(view->window);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400158}
159
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400160static struct view *
161view_create(struct display *display, uint32_t key, const char *filename)
162{
163 struct view *view;
164 gchar *basename;
165 gchar *title;
166 GError *error = NULL;
167
168 view = malloc(sizeof *view);
169 if (view == NULL)
170 return view;
171 memset(view, 0, sizeof *view);
172
173 basename = g_path_get_basename(filename);
174 title = g_strdup_printf("Wayland View - %s", basename);
175 g_free(basename);
176
177 view->filename = g_strdup(filename);
178
179 view->window = window_create(display, title,
180 100 * key, 100 * key, 500, 400);
181 view->display = display;
182
183 /* FIXME: Window uses key 1 for moves, need some kind of
184 * allocation scheme here. Or maybe just a real toolkit. */
185 view->key = key + 100;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400186
Kristian Høgsbergc8c37342010-06-25 11:19:22 -0400187 window_set_user_data(view->window, view);
188 window_set_redraw_handler(view->window, redraw_handler);
189 window_set_key_handler(view->window, key_handler);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400190 window_set_keyboard_focus_handler(view->window,
Kristian Høgsbergc8c37342010-06-25 11:19:22 -0400191 keyboard_focus_handler);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400192
193 view->document = poppler_document_new_from_file(view->filename,
194 NULL, &error);
195 view->page = 0;
196 view_draw(view);
197
198 return view;
199}
200
201static const GOptionEntry option_entries[] = {
202 { NULL }
203};
204
205int
206main(int argc, char *argv[])
207{
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400208 struct display *d;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400209 int i;
210
Kristian Høgsberg7824d812010-06-08 14:59:44 -0400211 d = display_create(&argc, &argv, option_entries);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400212
213 for (i = 1; i < argc; i++) {
214 struct view *view;
215
216 view = view_create (d, i, argv[i]);
217 }
218
Kristian Høgsberg7824d812010-06-08 14:59:44 -0400219 display_run(d);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400220
221 return 0;
222}