diff options
Diffstat (limited to 'swaylock/main.c')
-rw-r--r-- | swaylock/main.c | 138 |
1 files changed, 118 insertions, 20 deletions
diff --git a/swaylock/main.c b/swaylock/main.c index 200c1b5f..91c28bd2 100644 --- a/swaylock/main.c +++ b/swaylock/main.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <time.h> | 13 | #include <time.h> |
14 | #include <unistd.h> | 14 | #include <unistd.h> |
15 | #include <wayland-client.h> | 15 | #include <wayland-client.h> |
16 | #include <wordexp.h> | ||
16 | #include <wlr/util/log.h> | 17 | #include <wlr/util/log.h> |
17 | #include "swaylock/seat.h" | 18 | #include "swaylock/seat.h" |
18 | #include "swaylock/swaylock.h" | 19 | #include "swaylock/swaylock.h" |
@@ -20,9 +21,11 @@ | |||
20 | #include "pool-buffer.h" | 21 | #include "pool-buffer.h" |
21 | #include "cairo.h" | 22 | #include "cairo.h" |
22 | #include "log.h" | 23 | #include "log.h" |
24 | #include "stringop.h" | ||
23 | #include "util.h" | 25 | #include "util.h" |
24 | #include "wlr-input-inhibitor-unstable-v1-client-protocol.h" | 26 | #include "wlr-input-inhibitor-unstable-v1-client-protocol.h" |
25 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" | 27 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" |
28 | #include "xdg-output-unstable-v1-client-protocol.h" | ||
26 | 29 | ||
27 | void sway_terminate(int exit_code) { | 30 | void sway_terminate(int exit_code) { |
28 | exit(exit_code); | 31 | exit(exit_code); |
@@ -84,22 +87,23 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { | |||
84 | .closed = layer_surface_closed, | 87 | .closed = layer_surface_closed, |
85 | }; | 88 | }; |
86 | 89 | ||
87 | static void output_geometry(void *data, struct wl_output *output, int32_t x, | 90 | static void handle_wl_output_geometry(void *data, struct wl_output *output, int32_t x, |
88 | int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, | 91 | int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, |
89 | const char *make, const char *model, int32_t transform) { | 92 | const char *make, const char *model, int32_t transform) { |
90 | // Who cares | 93 | // Who cares |
91 | } | 94 | } |
92 | 95 | ||
93 | static void output_mode(void *data, struct wl_output *output, uint32_t flags, | 96 | static void handle_wl_output_mode(void *data, struct wl_output *output, uint32_t flags, |
94 | int32_t width, int32_t height, int32_t refresh) { | 97 | int32_t width, int32_t height, int32_t refresh) { |
95 | // Who cares | 98 | // Who cares |
96 | } | 99 | } |
97 | 100 | ||
98 | static void output_done(void *data, struct wl_output *output) { | 101 | static void handle_wl_output_done(void *data, struct wl_output *output) { |
99 | // Who cares | 102 | // Who cares |
100 | } | 103 | } |
101 | 104 | ||
102 | static void output_scale(void *data, struct wl_output *output, int32_t factor) { | 105 | static void handle_wl_output_scale(void *data, struct wl_output *output, |
106 | int32_t factor) { | ||
103 | struct swaylock_surface *surface = data; | 107 | struct swaylock_surface *surface = data; |
104 | surface->scale = factor; | 108 | surface->scale = factor; |
105 | if (surface->state->run_display) { | 109 | if (surface->state->run_display) { |
@@ -107,11 +111,46 @@ static void output_scale(void *data, struct wl_output *output, int32_t factor) { | |||
107 | } | 111 | } |
108 | } | 112 | } |
109 | 113 | ||
110 | struct wl_output_listener output_listener = { | 114 | struct wl_output_listener _wl_output_listener = { |
111 | .geometry = output_geometry, | 115 | .geometry = handle_wl_output_geometry, |
112 | .mode = output_mode, | 116 | .mode = handle_wl_output_mode, |
113 | .done = output_done, | 117 | .done = handle_wl_output_done, |
114 | .scale = output_scale, | 118 | .scale = handle_wl_output_scale, |
119 | }; | ||
120 | |||
121 | static void handle_xdg_output_logical_size(void *data, struct zxdg_output_v1 *output, | ||
122 | int width, int height) { | ||
123 | // Who cares | ||
124 | } | ||
125 | |||
126 | static void handle_xdg_output_logical_position(void *data, | ||
127 | struct zxdg_output_v1 *output, int x, int y) { | ||
128 | // Who cares | ||
129 | } | ||
130 | |||
131 | static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output, | ||
132 | const char *name) { | ||
133 | wlr_log(L_DEBUG, "output name is %s", name); | ||
134 | struct swaylock_surface *surface = data; | ||
135 | surface->xdg_output = output; | ||
136 | surface->output_name = strdup(name); | ||
137 | } | ||
138 | |||
139 | static void handle_xdg_output_description(void *data, struct zxdg_output_v1 *output, | ||
140 | const char *description) { | ||
141 | // Who cares | ||
142 | } | ||
143 | |||
144 | static void handle_xdg_output_done(void *data, struct zxdg_output_v1 *output) { | ||
145 | // Who cares | ||
146 | } | ||
147 | |||
148 | struct zxdg_output_v1_listener _xdg_output_listener = { | ||
149 | .logical_position = handle_xdg_output_logical_position, | ||
150 | .logical_size = handle_xdg_output_logical_size, | ||
151 | .done = handle_xdg_output_done, | ||
152 | .name = handle_xdg_output_name, | ||
153 | .description = handle_xdg_output_description, | ||
115 | }; | 154 | }; |
116 | 155 | ||
117 | static void handle_global(void *data, struct wl_registry *registry, | 156 | static void handle_global(void *data, struct wl_registry *registry, |
@@ -133,13 +172,16 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
133 | } else if (strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name) == 0) { | 172 | } else if (strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name) == 0) { |
134 | state->input_inhibit_manager = wl_registry_bind( | 173 | state->input_inhibit_manager = wl_registry_bind( |
135 | registry, name, &zwlr_input_inhibit_manager_v1_interface, 1); | 174 | registry, name, &zwlr_input_inhibit_manager_v1_interface, 1); |
175 | } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { | ||
176 | state->zxdg_output_manager = wl_registry_bind( | ||
177 | registry, name, &zxdg_output_manager_v1_interface, 2); | ||
136 | } else if (strcmp(interface, wl_output_interface.name) == 0) { | 178 | } else if (strcmp(interface, wl_output_interface.name) == 0) { |
137 | struct swaylock_surface *surface = | 179 | struct swaylock_surface *surface = |
138 | calloc(1, sizeof(struct swaylock_surface)); | 180 | calloc(1, sizeof(struct swaylock_surface)); |
139 | surface->state = state; | 181 | surface->state = state; |
140 | surface->output = wl_registry_bind(registry, name, | 182 | surface->output = wl_registry_bind(registry, name, |
141 | &wl_output_interface, 3); | 183 | &wl_output_interface, 3); |
142 | wl_output_add_listener(surface->output, &output_listener, surface); | 184 | wl_output_add_listener(surface->output, &_wl_output_listener, surface); |
143 | wl_list_insert(&state->surfaces, &surface->link); | 185 | wl_list_insert(&state->surfaces, &surface->link); |
144 | } | 186 | } |
145 | } | 187 | } |
@@ -154,6 +196,53 @@ static const struct wl_registry_listener registry_listener = { | |||
154 | .global_remove = handle_global_remove, | 196 | .global_remove = handle_global_remove, |
155 | }; | 197 | }; |
156 | 198 | ||
199 | static cairo_surface_t *select_image(struct swaylock_state *state, | ||
200 | struct swaylock_surface *surface) { | ||
201 | struct swaylock_image *image; | ||
202 | cairo_surface_t *default_image = NULL; | ||
203 | wl_list_for_each(image, &state->images, link) { | ||
204 | if (lenient_strcmp(image->output_name, surface->output_name) == 0) { | ||
205 | return image->cairo_surface; | ||
206 | } else if (!image->output_name) { | ||
207 | default_image = image->cairo_surface; | ||
208 | } | ||
209 | } | ||
210 | return default_image; | ||
211 | } | ||
212 | |||
213 | static void load_image(char *arg, struct swaylock_state *state) { | ||
214 | // [<output>:]<path> | ||
215 | struct swaylock_image *image = malloc(sizeof(struct swaylock_image)); | ||
216 | char *separator = strchr(arg, ':'); | ||
217 | if (separator) { | ||
218 | *separator = '\0'; | ||
219 | image->output_name = strdup(arg); | ||
220 | image->path = strdup(separator + 1); | ||
221 | } else { | ||
222 | image->output_name = NULL; | ||
223 | image->path = strdup(arg); | ||
224 | } | ||
225 | |||
226 | // Bash doesn't replace the ~ with $HOME if the output name is supplied | ||
227 | wordexp_t p; | ||
228 | if (wordexp(image->path, &p, 0) == 0) { | ||
229 | free(image->path); | ||
230 | image->path = strdup(p.we_wordv[0]); | ||
231 | wordfree(&p); | ||
232 | } | ||
233 | |||
234 | // Load the actual image | ||
235 | image->cairo_surface = load_background_image(image->path); | ||
236 | if (!image->cairo_surface) { | ||
237 | free(image); | ||
238 | return; | ||
239 | } | ||
240 | wl_list_insert(&state->images, &image->link); | ||
241 | state->args.mode = BACKGROUND_MODE_FILL; | ||
242 | wlr_log(L_DEBUG, "Loaded image %s for output %s", | ||
243 | image->path, image->output_name ? image->output_name : "*"); | ||
244 | } | ||
245 | |||
157 | static struct swaylock_state state; | 246 | static struct swaylock_state state; |
158 | 247 | ||
159 | int main(int argc, char **argv) { | 248 | int main(int argc, char **argv) { |
@@ -180,16 +269,15 @@ int main(int argc, char **argv) { | |||
180 | " -v, --version Show the version number and quit.\n" | 269 | " -v, --version Show the version number and quit.\n" |
181 | " -i, --image [<output>:]<path> Display the given image.\n" | 270 | " -i, --image [<output>:]<path> Display the given image.\n" |
182 | " -u, --no-unlock-indicator Disable the unlock indicator.\n" | 271 | " -u, --no-unlock-indicator Disable the unlock indicator.\n" |
183 | " -f, --daemonize Detach from the controlling terminal.\n" | 272 | " -f, --daemonize Detach from the controlling terminal.\n"; |
184 | " --socket <socket> Use the specified socket.\n"; | ||
185 | 273 | ||
186 | struct swaylock_args args = { | 274 | struct swaylock_args args = { |
187 | .mode = BACKGROUND_MODE_SOLID_COLOR, | 275 | .mode = BACKGROUND_MODE_SOLID_COLOR, |
188 | .color = 0xFFFFFFFF, | 276 | .color = 0xFFFFFFFF, |
189 | .show_indicator = true, | 277 | .show_indicator = true, |
190 | }; | 278 | }; |
191 | cairo_surface_t *background_image = NULL; | ||
192 | state.args = args; | 279 | state.args = args; |
280 | wl_list_init(&state.images); | ||
193 | wlr_log_init(L_DEBUG, NULL); | 281 | wlr_log_init(L_DEBUG, NULL); |
194 | 282 | ||
195 | int c; | 283 | int c; |
@@ -206,12 +294,7 @@ int main(int argc, char **argv) { | |||
206 | break; | 294 | break; |
207 | } | 295 | } |
208 | case 'i': | 296 | case 'i': |
209 | // TODO: Multiple background images (bleh) | 297 | load_image(optarg, &state); |
210 | background_image = load_background_image(optarg); | ||
211 | if (!background_image) { | ||
212 | return 1; | ||
213 | } | ||
214 | state.args.mode = BACKGROUND_MODE_FILL; | ||
215 | break; | 298 | break; |
216 | case 's': | 299 | case 's': |
217 | state.args.mode = parse_background_mode(optarg); | 300 | state.args.mode = parse_background_mode(optarg); |
@@ -261,6 +344,7 @@ int main(int argc, char **argv) { | |||
261 | if (!state.input_inhibit_manager) { | 344 | if (!state.input_inhibit_manager) { |
262 | wlr_log(L_ERROR, "Compositor does not support the input inhibitor " | 345 | wlr_log(L_ERROR, "Compositor does not support the input inhibitor " |
263 | "protocol, refusing to run insecurely"); | 346 | "protocol, refusing to run insecurely"); |
347 | return 1; | ||
264 | } | 348 | } |
265 | 349 | ||
266 | if (wl_list_empty(&state.surfaces)) { | 350 | if (wl_list_empty(&state.surfaces)) { |
@@ -268,9 +352,23 @@ int main(int argc, char **argv) { | |||
268 | return 0; | 352 | return 0; |
269 | } | 353 | } |
270 | 354 | ||
355 | if (state.zxdg_output_manager) { | ||
356 | struct swaylock_surface *surface; | ||
357 | wl_list_for_each(surface, &state.surfaces, link) { | ||
358 | surface->xdg_output = zxdg_output_manager_v1_get_xdg_output( | ||
359 | state.zxdg_output_manager, surface->output); | ||
360 | zxdg_output_v1_add_listener( | ||
361 | surface->xdg_output, &_xdg_output_listener, surface); | ||
362 | } | ||
363 | wl_display_roundtrip(state.display); | ||
364 | } else { | ||
365 | wlr_log(L_INFO, "Compositor does not support zxdg output manager, " | ||
366 | "images assigned to named outputs will not work"); | ||
367 | } | ||
368 | |||
271 | struct swaylock_surface *surface; | 369 | struct swaylock_surface *surface; |
272 | wl_list_for_each(surface, &state.surfaces, link) { | 370 | wl_list_for_each(surface, &state.surfaces, link) { |
273 | surface->image = background_image; | 371 | surface->image = select_image(&state, surface); |
274 | 372 | ||
275 | surface->surface = wl_compositor_create_surface(state.compositor); | 373 | surface->surface = wl_compositor_create_surface(state.compositor); |
276 | assert(surface->surface); | 374 | assert(surface->surface); |