blob: 401960cf5b76cf70868423924e9d20aa76a50d85 [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;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040055
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040056 gchar *filename;
57 PopplerDocument *document;
58 int page;
59 int fullscreen;
60 int focused;
61};
62
63static void
64view_draw(struct view *view)
65{
66 struct rectangle rectangle;
Kristian Høgsberg09531622010-06-14 23:22:15 -040067 cairo_surface_t *surface;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040068 cairo_t *cr;
69 PopplerPage *page;
70 double width, height, doc_aspect, window_aspect, scale;
71
Kristian Høgsberg09531622010-06-14 23:22:15 -040072 view->redraw_scheduled = 0;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040073
74 window_draw(view->window);
75
76 window_get_child_rectangle(view->window, &rectangle);
77
78 page = poppler_document_get_page(view->document, view->page);
79
Kristian Høgsberg09531622010-06-14 23:22:15 -040080 surface = window_get_surface(view->window);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040081
Kristian Høgsberg09531622010-06-14 23:22:15 -040082 cr = cairo_create(surface);
83 cairo_rectangle(cr, rectangle.x, rectangle.y,
84 rectangle.width, rectangle.height);
85 cairo_clip(cr);
86
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040087 cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
88 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
89 cairo_paint(cr);
90 poppler_page_get_size(page, &width, &height);
91 doc_aspect = width / height;
92 window_aspect = (double) rectangle.width / rectangle.height;
93 if (doc_aspect < window_aspect)
94 scale = rectangle.height / height;
95 else
96 scale = rectangle.width / width;
Kristian Høgsberg09531622010-06-14 23:22:15 -040097 cairo_translate(cr, rectangle.x, rectangle.y);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -040098 cairo_scale(cr, scale, scale);
99 cairo_translate(cr,
100 (rectangle.width - width * scale) / 2 / scale,
101 (rectangle.height - height * scale) / 2 / scale);
102 cairo_rectangle(cr, 0, 0, width, height);
103 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
104 cairo_set_source_rgb(cr, 1, 1, 1);
105 cairo_fill(cr);
106 poppler_page_render(page, cr);
107 cairo_destroy(cr);
108 g_object_unref(G_OBJECT(page));
109
Kristian Høgsberg478d9262010-06-08 20:34:11 -0400110 window_commit(view->window, 0);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400111}
112
113static gboolean
114view_idle_redraw(void *data)
115{
116 struct view *view = data;
117
118 view_draw(view);
119
120 return FALSE;
121}
122
123static void
124view_schedule_redraw(struct view *view)
125{
126 if (!view->redraw_scheduled) {
127 view->redraw_scheduled = 1;
128 g_idle_add(view_idle_redraw, view);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400129 }
130}
131
132static void
133key_handler(struct window *window, uint32_t key, uint32_t unicode,
134 uint32_t state, uint32_t modifiers, void *data)
135{
136 struct view *view = data;
137
138 switch (key) {
139 case KEY_F11:
140 if (!state)
141 break;
142 view->fullscreen ^= 1;
143 window_set_fullscreen(window, view->fullscreen);
144 view_schedule_redraw(view);
145 break;
146 case KEY_SPACE:
147 case KEY_PAGEDOWN:
148 if (!state)
149 break;
150 view->page++;
151 view_schedule_redraw(view);
152 break;
153 case KEY_BACKSPACE:
154 case KEY_PAGEUP:
155 if (!state)
156 break;
157 view->page--;
158 view_schedule_redraw(view);
159 break;
160 default:
161 break;
162 }
163}
164
165static void
166resize_handler(struct window *window, void *data)
167{
168 struct view *view = data;
169
170 view_schedule_redraw(view);
171}
172
173static void
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400174keyboard_focus_handler(struct window *window,
175 struct wl_input_device *device, void *data)
176{
177 struct view *view = data;
178
179 view->focused = (device != NULL);
180 view_schedule_redraw(view);
181}
182
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400183static struct view *
184view_create(struct display *display, uint32_t key, const char *filename)
185{
186 struct view *view;
187 gchar *basename;
188 gchar *title;
189 GError *error = NULL;
190
191 view = malloc(sizeof *view);
192 if (view == NULL)
193 return view;
194 memset(view, 0, sizeof *view);
195
196 basename = g_path_get_basename(filename);
197 title = g_strdup_printf("Wayland View - %s", basename);
198 g_free(basename);
199
200 view->filename = g_strdup(filename);
201
202 view->window = window_create(display, title,
203 100 * key, 100 * key, 500, 400);
204 view->display = display;
205
206 /* FIXME: Window uses key 1 for moves, need some kind of
207 * allocation scheme here. Or maybe just a real toolkit. */
208 view->key = key + 100;
209 view->redraw_scheduled = 1;
210
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400211 window_set_resize_handler(view->window, resize_handler, view);
212 window_set_key_handler(view->window, key_handler, view);
213 window_set_keyboard_focus_handler(view->window,
214 keyboard_focus_handler, view);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400215
216 view->document = poppler_document_new_from_file(view->filename,
217 NULL, &error);
218 view->page = 0;
219 view_draw(view);
220
221 return view;
222}
223
224static const GOptionEntry option_entries[] = {
225 { NULL }
226};
227
228int
229main(int argc, char *argv[])
230{
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400231 struct display *d;
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400232 int i;
233
Kristian Høgsberg7824d812010-06-08 14:59:44 -0400234 d = display_create(&argc, &argv, option_entries);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400235
236 for (i = 1; i < argc; i++) {
237 struct view *view;
238
239 view = view_create (d, i, argv[i]);
240 }
241
Kristian Høgsberg7824d812010-06-08 14:59:44 -0400242 display_run(d);
Kristian Høgsberg8f2f7732009-09-21 13:46:45 -0400243
244 return 0;
245}