blob: 8579804d1e8f9ac0cb7d602421c51624fbd2f6bc [file] [log] [blame]
Chris Wilson0de19eb2009-02-21 15:22:06 -05001/*
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>
Kristian Høgsbergf02a6492012-03-12 01:05:25 -040029#include <libgen.h>
Chris Wilson0de19eb2009-02-21 15:22:06 -050030#include <unistd.h>
31#include <math.h>
32#include <time.h>
33#include <cairo.h>
Chris Wilson0de19eb2009-02-21 15:22:06 -050034
Pekka Paalanen50719bc2011-11-22 14:18:50 +020035#include <wayland-client.h>
Chris Wilson0de19eb2009-02-21 15:22:06 -050036
37#include "window.h"
Kristian Høgsberg5a315bc2012-05-15 22:33:43 -040038#include "../shared/cairo-util.h"
Chris Wilson0de19eb2009-02-21 15:22:06 -050039
Chris Wilson0de19eb2009-02-21 15:22:06 -050040struct image {
41 struct window *window;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050042 struct widget *widget;
Chris Wilson0de19eb2009-02-21 15:22:06 -050043 struct display *display;
Kristian Høgsbergf02a6492012-03-12 01:05:25 -040044 char *filename;
45 cairo_surface_t *image;
Kristian Høgsbergdf0faf72012-07-23 22:00:21 -040046 int fullscreen;
Philipp Brüschweiler1f54f172012-08-13 21:16:47 +020047 int *image_counter;
Chris Wilson0de19eb2009-02-21 15:22:06 -050048};
49
50static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050051redraw_handler(struct widget *widget, void *data)
Chris Wilson0de19eb2009-02-21 15:22:06 -050052{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050053 struct image *image = data;
Kristian Høgsbergda846ca2011-01-11 10:00:52 -050054 struct rectangle allocation;
Chris Wilson0de19eb2009-02-21 15:22:06 -050055 cairo_t *cr;
Kristian Høgsberge164e4e2011-01-21 11:35:05 -050056 cairo_surface_t *surface;
Kristian Høgsbergf02a6492012-03-12 01:05:25 -040057 double width, height, doc_aspect, window_aspect, scale;
Chris Wilson0de19eb2009-02-21 15:22:06 -050058
Kristian Høgsbergbb977002012-01-10 19:11:42 -050059 widget_get_allocation(image->widget, &allocation);
Chris Wilson0de19eb2009-02-21 15:22:06 -050060
Kristian Høgsberge164e4e2011-01-21 11:35:05 -050061 surface = window_get_surface(image->window);
Kristian Høgsberg09531622010-06-14 23:22:15 -040062 cr = cairo_create(surface);
Kristian Høgsbergbb977002012-01-10 19:11:42 -050063 widget_get_allocation(image->widget, &allocation);
Kristian Høgsberge164e4e2011-01-21 11:35:05 -050064 cairo_rectangle(cr, allocation.x, allocation.y,
65 allocation.width, allocation.height);
66 cairo_clip(cr);
67 cairo_push_group(cr);
68 cairo_translate(cr, allocation.x, allocation.y);
69
Chris Wilson0de19eb2009-02-21 15:22:06 -050070 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
71 cairo_set_source_rgba(cr, 0, 0, 0, 1);
72 cairo_paint(cr);
Kristian Høgsbergf02a6492012-03-12 01:05:25 -040073
74 width = cairo_image_surface_get_width(image->image);
75 height = cairo_image_surface_get_height(image->image);
76 doc_aspect = width / height;
77 window_aspect = (double) allocation.width / allocation.height;
78 if (doc_aspect < window_aspect)
79 scale = allocation.height / height;
80 else
81 scale = allocation.width / width;
82 cairo_scale(cr, scale, scale);
83 cairo_translate(cr,
84 (allocation.width - width * scale) / 2 / scale,
85 (allocation.height - height * scale) / 2 / scale);
86
87 cairo_set_source_surface(cr, image->image, 0, 0);
Chris Wilson0de19eb2009-02-21 15:22:06 -050088 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
89 cairo_paint(cr);
Chris Wilson0de19eb2009-02-21 15:22:06 -050090
Kristian Høgsberge164e4e2011-01-21 11:35:05 -050091 cairo_pop_group_to_source(cr);
92 cairo_paint(cr);
93 cairo_destroy(cr);
94
Kristian Høgsberg09531622010-06-14 23:22:15 -040095 cairo_surface_destroy(surface);
Chris Wilson0de19eb2009-02-21 15:22:06 -050096}
97
Kristian Høgsberg80d746f2010-06-14 23:52:50 -040098static void
Kristian Høgsberga341fa02010-01-24 18:10:15 -050099keyboard_focus_handler(struct window *window,
Kristian Høgsberg43788b12010-07-28 23:50:12 -0400100 struct input *device, void *data)
Kristian Høgsberga341fa02010-01-24 18:10:15 -0500101{
102 struct image *image = data;
103
Kristian Høgsberg80d746f2010-06-14 23:52:50 -0400104 window_schedule_redraw(image->window);
Kristian Høgsberga341fa02010-01-24 18:10:15 -0500105}
106
Kristian Høgsbergdf0faf72012-07-23 22:00:21 -0400107static void
108fullscreen_handler(struct window *window, void *data)
109{
110 struct image *image = data;
111
112 image->fullscreen ^= 1;
113 window_set_fullscreen(window, image->fullscreen);
114}
115
Philipp Brüschweiler1f54f172012-08-13 21:16:47 +0200116static void
117close_handler(struct window *window, void *data)
118{
119 struct image *image = data;
120
121 *image->image_counter -= 1;
122
123 if (*image->image_counter == 0)
124 display_exit(image->display);
125
126 widget_destroy(image->widget);
127 window_destroy(image->window);
128
129 free(image);
130}
131
Chris Wilson0de19eb2009-02-21 15:22:06 -0500132static struct image *
Philipp Brüschweiler1f54f172012-08-13 21:16:47 +0200133image_create(struct display *display, const char *filename,
134 int *image_counter)
Chris Wilson0de19eb2009-02-21 15:22:06 -0500135{
136 struct image *image;
Kristian Høgsbergf02a6492012-03-12 01:05:25 -0400137 char *b, *copy, title[512];;
Chris Wilson0de19eb2009-02-21 15:22:06 -0500138
139 image = malloc(sizeof *image);
140 if (image == NULL)
141 return image;
142 memset(image, 0, sizeof *image);
143
Kristian Høgsbergf02a6492012-03-12 01:05:25 -0400144 copy = strdup(filename);
145 b = basename(copy);
146 snprintf(title, sizeof title, "Wayland Image - %s", b);
147 free(copy);
Chris Wilson0de19eb2009-02-21 15:22:06 -0500148
Kristian Høgsbergf02a6492012-03-12 01:05:25 -0400149 image->filename = strdup(filename);
150 image->image = load_cairo_surface(filename);
Juan Zhao19a4c2d2012-08-06 19:45:43 -0700151
152 if (!image->image) {
153 fprintf(stderr, "could not find the image %s!\n", b);
154 return NULL;
155 }
156
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500157 image->window = window_create(display);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500158 image->widget = frame_create(image->window, image);
Kristian Høgsberg248c1b62011-01-21 18:03:15 -0500159 window_set_title(image->window, title);
Chris Wilson0de19eb2009-02-21 15:22:06 -0500160 image->display = display;
Philipp Brüschweiler1f54f172012-08-13 21:16:47 +0200161 image->image_counter = image_counter;
162 *image_counter += 1;
Chris Wilson0de19eb2009-02-21 15:22:06 -0500163
Kristian Høgsbergc8c37342010-06-25 11:19:22 -0400164 window_set_user_data(image->window, image);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500165 widget_set_redraw_handler(image->widget, redraw_handler);
Kristian Høgsberg43788b12010-07-28 23:50:12 -0400166 window_set_keyboard_focus_handler(image->window,
167 keyboard_focus_handler);
Kristian Høgsbergdf0faf72012-07-23 22:00:21 -0400168 window_set_fullscreen_handler(image->window, fullscreen_handler);
Philipp Brüschweiler1f54f172012-08-13 21:16:47 +0200169 window_set_close_handler(image->window, close_handler);
Chris Wilson0de19eb2009-02-21 15:22:06 -0500170
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500171 widget_schedule_resize(image->widget, 500, 400);
Chris Wilson0de19eb2009-02-21 15:22:06 -0500172
173 return image;
174}
175
Chris Wilson0de19eb2009-02-21 15:22:06 -0500176int
177main(int argc, char *argv[])
178{
Chris Wilson0de19eb2009-02-21 15:22:06 -0500179 struct display *d;
Chris Wilson0de19eb2009-02-21 15:22:06 -0500180 int i;
Philipp Brüschweiler1f54f172012-08-13 21:16:47 +0200181 int image_counter = 0;
Chris Wilson0de19eb2009-02-21 15:22:06 -0500182
Kristian Høgsbergbcacef12012-03-11 21:05:57 -0400183 d = display_create(argc, argv);
Yuval Fledele9f5e362010-11-22 21:34:19 +0200184 if (d == NULL) {
185 fprintf(stderr, "failed to create display: %m\n");
186 return -1;
187 }
Chris Wilson0de19eb2009-02-21 15:22:06 -0500188
Kristian Høgsberg00439612011-01-25 15:16:01 -0500189 for (i = 1; i < argc; i++)
Philipp Brüschweiler1f54f172012-08-13 21:16:47 +0200190 image_create(d, argv[i], &image_counter);
Chris Wilson0de19eb2009-02-21 15:22:06 -0500191
Philipp Brüschweiler1f54f172012-08-13 21:16:47 +0200192 if (image_counter > 0)
193 display_run(d);
Chris Wilson0de19eb2009-02-21 15:22:06 -0500194
195 return 0;
196}