diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-03-27 15:25:25 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-03-28 14:25:19 -0400 |
commit | 632bb948b7ffbb08a6e965dabf88347afd0a1fa8 (patch) | |
tree | cbd9d4e4e3a7c605d2b0a5e3e66ce35554a74c4b /swaybg | |
parent | Add client protocols and swaybg skeleton (diff) | |
download | sway-632bb948b7ffbb08a6e965dabf88347afd0a1fa8.tar.gz sway-632bb948b7ffbb08a6e965dabf88347afd0a1fa8.tar.zst sway-632bb948b7ffbb08a6e965dabf88347afd0a1fa8.zip |
Add solid-color rendering to swaybg
Diffstat (limited to 'swaybg')
-rw-r--r-- | swaybg/main.c | 187 | ||||
-rw-r--r-- | swaybg/meson.build | 18 |
2 files changed, 203 insertions, 2 deletions
diff --git a/swaybg/main.c b/swaybg/main.c index 94e98228..4473869b 100644 --- a/swaybg/main.c +++ b/swaybg/main.c | |||
@@ -6,6 +6,10 @@ | |||
6 | #include <time.h> | 6 | #include <time.h> |
7 | #include <wayland-client.h> | 7 | #include <wayland-client.h> |
8 | #include <wlr/util/log.h> | 8 | #include <wlr/util/log.h> |
9 | #include "buffer_pool.h" | ||
10 | #include "cairo.h" | ||
11 | #include "util.h" | ||
12 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" | ||
9 | 13 | ||
10 | enum scaling_mode { | 14 | enum scaling_mode { |
11 | SCALING_MODE_STRETCH, | 15 | SCALING_MODE_STRETCH, |
@@ -13,6 +17,31 @@ enum scaling_mode { | |||
13 | SCALING_MODE_FIT, | 17 | SCALING_MODE_FIT, |
14 | SCALING_MODE_CENTER, | 18 | SCALING_MODE_CENTER, |
15 | SCALING_MODE_TILE, | 19 | SCALING_MODE_TILE, |
20 | SCALING_MODE_SOLID_COLOR, | ||
21 | }; | ||
22 | |||
23 | struct swaybg_args { | ||
24 | int output_idx; | ||
25 | const char *path; | ||
26 | enum scaling_mode mode; | ||
27 | }; | ||
28 | |||
29 | struct swaybg_state { | ||
30 | const struct swaybg_args *args; | ||
31 | |||
32 | struct wl_display *display; | ||
33 | struct wl_compositor *compositor; | ||
34 | struct zwlr_layer_shell_v1 *layer_shell; | ||
35 | struct wl_shm *shm; | ||
36 | |||
37 | struct wl_output *output; | ||
38 | struct wl_surface *surface; | ||
39 | struct zwlr_layer_surface_v1 *layer_surface; | ||
40 | |||
41 | bool run_display; | ||
42 | uint32_t width, height; | ||
43 | struct pool_buffer buffers[2]; | ||
44 | struct pool_buffer *current_buffer; | ||
16 | }; | 45 | }; |
17 | 46 | ||
18 | bool is_valid_color(const char *color) { | 47 | bool is_valid_color(const char *color) { |
@@ -33,7 +62,165 @@ bool is_valid_color(const char *color) { | |||
33 | return true; | 62 | return true; |
34 | } | 63 | } |
35 | 64 | ||
65 | static void render_frame(struct swaybg_state *state) { | ||
66 | if (!state->run_display) { | ||
67 | return; | ||
68 | } | ||
69 | |||
70 | state->current_buffer = get_next_buffer(state->shm, | ||
71 | state->buffers, state->width, state->height); | ||
72 | cairo_t *cairo = state->current_buffer->cairo; | ||
73 | |||
74 | switch (state->args->mode) { | ||
75 | case SCALING_MODE_SOLID_COLOR: | ||
76 | cairo_set_source_u32(cairo, parse_color(state->args->path)); | ||
77 | cairo_paint(cairo); | ||
78 | break; | ||
79 | default: | ||
80 | exit(1); | ||
81 | break; | ||
82 | } | ||
83 | |||
84 | wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); | ||
85 | wl_surface_damage(state->surface, 0, 0, state->width, state->height); | ||
86 | wl_surface_commit(state->surface); | ||
87 | } | ||
88 | |||
89 | static void layer_surface_configure(void *data, | ||
90 | struct zwlr_layer_surface_v1 *surface, | ||
91 | uint32_t serial, uint32_t width, uint32_t height) { | ||
92 | struct swaybg_state *state = data; | ||
93 | state->width = width; | ||
94 | state->height = height; | ||
95 | render_frame(state); | ||
96 | zwlr_layer_surface_v1_ack_configure(surface, serial); | ||
97 | } | ||
98 | |||
99 | static void layer_surface_closed(void *data, | ||
100 | struct zwlr_layer_surface_v1 *surface) { | ||
101 | struct swaybg_state *state = data; | ||
102 | zwlr_layer_surface_v1_destroy(state->layer_surface); | ||
103 | wl_surface_destroy(state->surface); | ||
104 | state->run_display = false; | ||
105 | } | ||
106 | |||
107 | struct zwlr_layer_surface_v1_listener layer_surface_listener = { | ||
108 | .configure = layer_surface_configure, | ||
109 | .closed = layer_surface_closed, | ||
110 | }; | ||
111 | |||
112 | static void handle_global(void *data, struct wl_registry *registry, | ||
113 | uint32_t name, const char *interface, uint32_t version) { | ||
114 | struct swaybg_state *state = data; | ||
115 | if (strcmp(interface, wl_compositor_interface.name) == 0) { | ||
116 | state->compositor = wl_registry_bind(registry, name, | ||
117 | &wl_compositor_interface, 1); | ||
118 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { | ||
119 | state->shm = wl_registry_bind(registry, name, | ||
120 | &wl_shm_interface, 1); | ||
121 | } else if (strcmp(interface, wl_output_interface.name) == 0) { | ||
122 | static int output_idx = 0; | ||
123 | if (output_idx == state->args->output_idx) { | ||
124 | state->output = wl_registry_bind(registry, name, | ||
125 | &wl_output_interface, 1); | ||
126 | } | ||
127 | output_idx++; | ||
128 | } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { | ||
129 | state->layer_shell = wl_registry_bind( | ||
130 | registry, name, &zwlr_layer_shell_v1_interface, 1); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void handle_global_remove(void *data, struct wl_registry *registry, | ||
135 | uint32_t name) { | ||
136 | // who cares | ||
137 | } | ||
138 | |||
139 | static const struct wl_registry_listener registry_listener = { | ||
140 | .global = handle_global, | ||
141 | .global_remove = handle_global_remove, | ||
142 | }; | ||
143 | |||
36 | int main(int argc, const char **argv) { | 144 | int main(int argc, const char **argv) { |
145 | struct swaybg_args args = {0}; | ||
146 | struct swaybg_state state = {0}; | ||
147 | state.args = &args; | ||
37 | wlr_log_init(L_DEBUG, NULL); | 148 | wlr_log_init(L_DEBUG, NULL); |
149 | |||
150 | if (argc != 4) { | ||
151 | wlr_log(L_ERROR, "Do not run this program manually. " | ||
152 | "See man 5 sway and look for output options."); | ||
153 | return 1; | ||
154 | } | ||
155 | args.output_idx = atoi(argv[1]); | ||
156 | args.path = argv[2]; | ||
157 | args.mode = atoi(argv[3]); | ||
158 | |||
159 | args.mode = SCALING_MODE_STRETCH; | ||
160 | if (strcmp(argv[3], "stretch") == 0) { | ||
161 | args.mode = SCALING_MODE_STRETCH; | ||
162 | } else if (strcmp(argv[3], "fill") == 0) { | ||
163 | args.mode = SCALING_MODE_FILL; | ||
164 | } else if (strcmp(argv[3], "fit") == 0) { | ||
165 | args.mode = SCALING_MODE_FIT; | ||
166 | } else if (strcmp(argv[3], "center") == 0) { | ||
167 | args.mode = SCALING_MODE_CENTER; | ||
168 | } else if (strcmp(argv[3], "tile") == 0) { | ||
169 | args.mode = SCALING_MODE_TILE; | ||
170 | } else if (strcmp(argv[3], "solid_color") == 0) { | ||
171 | args.mode = SCALING_MODE_SOLID_COLOR; | ||
172 | } else { | ||
173 | wlr_log(L_ERROR, "Unsupported scaling mode: %s", argv[3]); | ||
174 | return 1; | ||
175 | } | ||
176 | |||
177 | state.display = wl_display_connect(NULL); | ||
178 | if (!state.display) { | ||
179 | wlr_log(L_ERROR, "Failed to create display\n"); | ||
180 | return 1; | ||
181 | } | ||
182 | |||
183 | struct wl_registry *registry = wl_display_get_registry(state.display); | ||
184 | wl_registry_add_listener(registry, ®istry_listener, &state); | ||
185 | wl_display_roundtrip(state.display); | ||
186 | |||
187 | if (!state.compositor) { | ||
188 | wlr_log(L_DEBUG, "wl-compositor not available"); | ||
189 | return 1; | ||
190 | } | ||
191 | if (!state.layer_shell) { | ||
192 | wlr_log(L_ERROR, "layer-shell not available"); | ||
193 | return 1; | ||
194 | } | ||
195 | |||
196 | state.surface = wl_compositor_create_surface(state.compositor); | ||
197 | if (!state.surface) { | ||
198 | wlr_log(L_ERROR, "failed to create wl_surface"); | ||
199 | return 1; | ||
200 | } | ||
201 | |||
202 | state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( | ||
203 | state.layer_shell, state.surface, state.output, | ||
204 | ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); | ||
205 | if (!state.layer_surface) { | ||
206 | wlr_log(L_ERROR, "failed to create zwlr_layer_surface"); | ||
207 | return 1; | ||
208 | } | ||
209 | zwlr_layer_surface_v1_set_size(state.layer_surface, 0, 0); | ||
210 | zwlr_layer_surface_v1_set_anchor(state.layer_surface, | ||
211 | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | | ||
212 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | | ||
213 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | | ||
214 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); | ||
215 | zwlr_layer_surface_v1_add_listener(state.layer_surface, | ||
216 | &layer_surface_listener, &state); | ||
217 | wl_surface_commit(state.surface); | ||
218 | wl_display_roundtrip(state.display); | ||
219 | |||
220 | state.run_display = true; | ||
221 | render_frame(&state); | ||
222 | while (wl_display_dispatch(state.display) != -1 && state.run_display) { | ||
223 | // This space intentionally left blank | ||
224 | } | ||
38 | return 0; | 225 | return 0; |
39 | } | 226 | } |
diff --git a/swaybg/meson.build b/swaybg/meson.build index 47315023..7f5d6bd1 100644 --- a/swaybg/meson.build +++ b/swaybg/meson.build | |||
@@ -1,8 +1,22 @@ | |||
1 | deps = [ | ||
2 | cairo, | ||
3 | jsonc, | ||
4 | math, | ||
5 | pango, | ||
6 | pangocairo, | ||
7 | sway_protos, | ||
8 | wayland_client, | ||
9 | ] | ||
10 | |||
11 | if gdk_pixbuf.found() | ||
12 | deps += [gdk_pixbuf] | ||
13 | endif | ||
14 | |||
1 | executable( | 15 | executable( |
2 | 'swaybg', | 16 | 'swaybg', |
3 | 'main.c', | 17 | 'main.c', |
4 | include_directories: [sway_inc], | 18 | include_directories: [sway_inc], |
5 | dependencies: [wayland_client, sway_protos, jsonc, wlroots], | 19 | dependencies: deps, |
6 | link_with: [lib_sway_common], | 20 | link_with: [lib_sway_common, lib_sway_client], |
7 | install: true | 21 | install: true |
8 | ) | 22 | ) |