aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2018-04-02 21:57:13 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2018-04-04 18:47:48 -0400
commita28730edee1896242012f80fd0e63e7966652e02 (patch)
treee85d2479ce1b77e23b3c3e34c1d9e0bf87ed30f0
parentMerge pull request #1731 from acrisci/ipc-window-events (diff)
downloadsway-a28730edee1896242012f80fd0e63e7966652e02.tar.gz
sway-a28730edee1896242012f80fd0e63e7966652e02.tar.zst
sway-a28730edee1896242012f80fd0e63e7966652e02.zip
Move swaybg background rendering into common/
swaylock will use it too
-rw-r--r--common/background-image.c100
-rw-r--r--common/meson.build20
-rw-r--r--include/background-image.h19
-rw-r--r--swaybg/main.c113
4 files changed, 133 insertions, 119 deletions
diff --git a/common/background-image.c b/common/background-image.c
new file mode 100644
index 00000000..2988c2e2
--- /dev/null
+++ b/common/background-image.c
@@ -0,0 +1,100 @@
1#include <assert.h>
2#include <stdbool.h>
3#include <wlr/util/log.h>
4#include "background-image.h"
5#include "cairo.h"
6
7cairo_surface_t *load_background_image(const char *path) {
8 cairo_surface_t *image;
9#ifdef HAVE_GDK_PIXBUF
10 GError *err = NULL;
11 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err);
12 if (!pixbuf) {
13 wlr_log(L_ERROR, "Failed to load background image.");
14 return false;
15 }
16 image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf);
17 g_object_unref(pixbuf);
18#else
19 image = cairo_image_surface_create_from_png(path);
20#endif //HAVE_GDK_PIXBUF
21 if (!image) {
22 wlr_log(L_ERROR, "Failed to read background image.");
23 return NULL;
24 }
25 if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) {
26 wlr_log(L_ERROR, "Failed to read background image: %s."
27#ifndef HAVE_GDK_PIXBUF
28 "\nSway was compiled without gdk_pixbuf support, so only"
29 "\nPNG images can be loaded. This is the likely cause."
30#endif //HAVE_GDK_PIXBUF
31 , cairo_status_to_string(cairo_surface_status(image)));
32 return NULL;
33 }
34 return image;
35}
36
37void render_background_image(cairo_t *cairo, cairo_surface_t *image,
38 enum background_mode mode, int buffer_width, int buffer_height,
39 int buffer_scale) {
40 double width = cairo_image_surface_get_width(image);
41 double height = cairo_image_surface_get_height(image);
42
43 switch (mode) {
44 case BACKGROUND_MODE_STRETCH:
45 cairo_scale(cairo,
46 (double)buffer_width / width,
47 (double)buffer_height / height);
48 cairo_set_source_surface(cairo, image, 0, 0);
49 break;
50 case BACKGROUND_MODE_FILL: {
51 double window_ratio = (double)buffer_width / buffer_height;
52 double bg_ratio = width / height;
53
54 if (window_ratio > bg_ratio) {
55 double scale = (double)buffer_width / width;
56 cairo_scale(cairo, scale, scale);
57 cairo_set_source_surface(cairo, image,
58 0, (double)buffer_height / 2 / scale - height / 2);
59 } else {
60 double scale = (double)buffer_height / height;
61 cairo_scale(cairo, scale, scale);
62 cairo_set_source_surface(cairo, image,
63 (double)buffer_width / 2 / scale - width / 2, 0);
64 }
65 break;
66 }
67 case BACKGROUND_MODE_FIT: {
68 double window_ratio = (double)buffer_width / buffer_height;
69 double bg_ratio = width / height;
70
71 if (window_ratio > bg_ratio) {
72 double scale = (double)buffer_height / height;
73 cairo_scale(cairo, scale, scale);
74 cairo_set_source_surface(cairo, image,
75 (double)buffer_width / 2 / scale - width / 2, 0);
76 } else {
77 double scale = (double)buffer_width / width;
78 cairo_scale(cairo, scale, scale);
79 cairo_set_source_surface(cairo, image,
80 0, (double)buffer_height / 2 / scale - height / 2);
81 }
82 break;
83 }
84 case BACKGROUND_MODE_CENTER:
85 cairo_set_source_surface(cairo, image,
86 (double)buffer_width / 2 - width / 2,
87 (double)buffer_height / 2 - height / 2);
88 break;
89 case BACKGROUND_MODE_TILE: {
90 cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
91 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
92 cairo_set_source(cairo, pattern);
93 break;
94 }
95 case BACKGROUND_MODE_SOLID_COLOR:
96 assert(0);
97 break;
98 }
99 cairo_paint(cairo);
100}
diff --git a/common/meson.build b/common/meson.build
index 4ad47077..851e7bbf 100644
--- a/common/meson.build
+++ b/common/meson.build
@@ -1,17 +1,7 @@
1deps = [
2 cairo,
3 pango,
4 pangocairo,
5 wlroots
6]
7
8if gdk_pixbuf.found()
9 deps += [gdk_pixbuf]
10endif
11
12lib_sway_common = static_library( 1lib_sway_common = static_library(
13 'sway-common', 2 'sway-common',
14 files( 3 files(
4 'background-image.c',
15 'cairo.c', 5 'cairo.c',
16 'ipc-client.c', 6 'ipc-client.c',
17 'log.c', 7 'log.c',
@@ -21,6 +11,12 @@ lib_sway_common = static_library(
21 'stringop.c', 11 'stringop.c',
22 'util.c' 12 'util.c'
23 ), 13 ),
24 dependencies: deps, 14 dependencies: [
15 cairo,
16 gdk_pixbuf,
17 pango,
18 pangocairo,
19 wlroots
20 ],
25 include_directories: sway_inc 21 include_directories: sway_inc
26) 22)
diff --git a/include/background-image.h b/include/background-image.h
new file mode 100644
index 00000000..e160e63d
--- /dev/null
+++ b/include/background-image.h
@@ -0,0 +1,19 @@
1#ifndef _SWAY_BACKGROUND_IMAGE_H
2#define _SWAY_BACKGROUND_IMAGE_H
3#include "cairo.h"
4
5enum background_mode {
6 BACKGROUND_MODE_STRETCH,
7 BACKGROUND_MODE_FILL,
8 BACKGROUND_MODE_FIT,
9 BACKGROUND_MODE_CENTER,
10 BACKGROUND_MODE_TILE,
11 BACKGROUND_MODE_SOLID_COLOR,
12};
13
14cairo_surface_t *load_background_image(const char *path);
15void render_background_image(cairo_t *cairo, cairo_surface_t *image,
16 enum background_mode mode, int buffer_width, int buffer_height,
17 int buffer_scale);
18
19#endif
diff --git a/swaybg/main.c b/swaybg/main.c
index c282a707..ffefcd08 100644
--- a/swaybg/main.c
+++ b/swaybg/main.c
@@ -7,20 +7,12 @@
7#include <time.h> 7#include <time.h>
8#include <wayland-client.h> 8#include <wayland-client.h>
9#include <wlr/util/log.h> 9#include <wlr/util/log.h>
10#include "background-image.h"
10#include "pool-buffer.h" 11#include "pool-buffer.h"
11#include "cairo.h" 12#include "cairo.h"
12#include "util.h" 13#include "util.h"
13#include "wlr-layer-shell-unstable-v1-client-protocol.h" 14#include "wlr-layer-shell-unstable-v1-client-protocol.h"
14 15
15enum background_mode {
16 BACKGROUND_MODE_STRETCH,
17 BACKGROUND_MODE_FILL,
18 BACKGROUND_MODE_FIT,
19 BACKGROUND_MODE_CENTER,
20 BACKGROUND_MODE_TILE,
21 BACKGROUND_MODE_SOLID_COLOR,
22};
23
24struct swaybg_args { 16struct swaybg_args {
25 int output_idx; 17 int output_idx;
26 const char *path; 18 const char *path;
@@ -71,85 +63,16 @@ bool is_valid_color(const char *color) {
71 return true; 63 return true;
72} 64}
73 65
74static void render_image(struct swaybg_state *state) {
75 cairo_t *cairo = state->current_buffer->cairo;
76 cairo_surface_t *image = state->context.image;
77 double width = cairo_image_surface_get_width(image);
78 double height = cairo_image_surface_get_height(image);
79 int buffer_width = state->width * state->scale;
80 int buffer_height = state->height * state->scale;
81
82 switch (state->args->mode) {
83 case BACKGROUND_MODE_STRETCH:
84 cairo_scale(cairo, (double)buffer_width / width,
85 (double)buffer_height / height);
86 cairo_set_source_surface(cairo, image, 0, 0);
87 break;
88 case BACKGROUND_MODE_FILL: {
89 double window_ratio = (double)buffer_width / buffer_height;
90 double bg_ratio = width / height;
91
92 if (window_ratio > bg_ratio) {
93 double scale = (double)buffer_width / width;
94 cairo_scale(cairo, scale, scale);
95 cairo_set_source_surface(cairo, image,
96 0, (double)buffer_height / 2 / scale - height / 2);
97 } else {
98 double scale = (double)buffer_height / height;
99 cairo_scale(cairo, scale, scale);
100 cairo_set_source_surface(cairo, image,
101 (double)buffer_width / 2 / scale - width / 2, 0);
102 }
103 break;
104 }
105 case BACKGROUND_MODE_FIT: {
106 double window_ratio = (double)buffer_width / buffer_height;
107 double bg_ratio = width / height;
108
109 if (window_ratio > bg_ratio) {
110 double scale = (double)buffer_height / height;
111 cairo_scale(cairo, scale, scale);
112 cairo_set_source_surface(cairo, image,
113 (double)buffer_width / 2 / scale - width / 2, 0);
114 } else {
115 double scale = (double)buffer_width / width;
116 cairo_scale(cairo, scale, scale);
117 cairo_set_source_surface(cairo, image,
118 0, (double)buffer_height / 2 / scale - height / 2);
119 }
120 break;
121 }
122 case BACKGROUND_MODE_CENTER:
123 cairo_set_source_surface(cairo, image,
124 (double)buffer_width / 2 - width / 2,
125 (double)buffer_height / 2 - height / 2);
126 break;
127 case BACKGROUND_MODE_TILE: {
128 cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
129 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
130 cairo_set_source(cairo, pattern);
131 break;
132 }
133 case BACKGROUND_MODE_SOLID_COLOR:
134 assert(0);
135 break;
136 }
137 cairo_paint(cairo);
138}
139
140static void render_frame(struct swaybg_state *state) { 66static void render_frame(struct swaybg_state *state) {
141 state->current_buffer = get_next_buffer(state->shm, state->buffers, 67 state->current_buffer = get_next_buffer(state->shm, state->buffers,
142 state->width * state->scale, state->height * state->scale); 68 state->width * state->scale, state->height * state->scale);
143 cairo_t *cairo = state->current_buffer->cairo; 69 cairo_t *cairo = state->current_buffer->cairo;
144 70 if (state->args->mode == BACKGROUND_MODE_SOLID_COLOR) {
145 switch (state->args->mode) {
146 case BACKGROUND_MODE_SOLID_COLOR:
147 cairo_set_source_u32(cairo, state->context.color); 71 cairo_set_source_u32(cairo, state->context.color);
148 cairo_paint(cairo); 72 cairo_paint(cairo);
149 break; 73 } else {
150 default: 74 render_background_image(cairo, state->context.image,
151 render_image(state); 75 state->args->mode, state->width, state->height, state->scale);
152 break;
153 } 76 }
154 77
155 wl_surface_set_buffer_scale(state->surface, state->scale); 78 wl_surface_set_buffer_scale(state->surface, state->scale);
@@ -163,31 +86,7 @@ static bool prepare_context(struct swaybg_state *state) {
163 state->context.color = parse_color(state->args->path); 86 state->context.color = parse_color(state->args->path);
164 return is_valid_color(state->args->path); 87 return is_valid_color(state->args->path);
165 } 88 }
166#ifdef HAVE_GDK_PIXBUF 89 if (!(state->context.image = load_background_image(state->args->path))) {
167 GError *err = NULL;
168 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(state->args->path, &err);
169 if (!pixbuf) {
170 wlr_log(L_ERROR, "Failed to load background image.");
171 return false;
172 }
173 state->context.image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf);
174 g_object_unref(pixbuf);
175#else
176 state->context.image = cairo_image_surface_create_from_png(
177 state->args->path);
178#endif //HAVE_GDK_PIXBUF
179 if (!state->context.image) {
180 wlr_log(L_ERROR, "Failed to read background image.");
181 return false;
182 }
183 if (cairo_surface_status(state->context.image) != CAIRO_STATUS_SUCCESS) {
184 wlr_log(L_ERROR, "Failed to read background image: %s."
185#ifndef HAVE_GDK_PIXBUF
186 "\nSway was compiled without gdk_pixbuf support, so only"
187 "\nPNG images can be loaded. This is the likely cause."
188#endif //HAVE_GDK_PIXBUF
189 , cairo_status_to_string(
190 cairo_surface_status(state->context.image)));
191 return false; 90 return false;
192 } 91 }
193 return true; 92 return true;