diff options
author | Drew DeVault <sir@cmpwn.com> | 2016-01-25 15:28:38 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2016-01-25 15:28:38 -0500 |
commit | d2af1f33951220c2a9fc691034084d7276aafbc5 (patch) | |
tree | d6324c6b73108c84d6609cd7eb79aad3a0172473 | |
parent | Merge pull request #474 from christophgysin/swaylock_pam (diff) | |
parent | swaylock: support --color (diff) | |
download | sway-d2af1f33951220c2a9fc691034084d7276aafbc5.tar.gz sway-d2af1f33951220c2a9fc691034084d7276aafbc5.tar.zst sway-d2af1f33951220c2a9fc691034084d7276aafbc5.zip |
Merge pull request #475 from christophgysin/swaylock_color
swaylock: implement --color
-rw-r--r-- | swaylock/main.c | 235 |
1 files changed, 135 insertions, 100 deletions
diff --git a/swaylock/main.c b/swaylock/main.c index 9530b6dc..98e26839 100644 --- a/swaylock/main.c +++ b/swaylock/main.c | |||
@@ -115,14 +115,100 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod | |||
115 | } | 115 | } |
116 | } | 116 | } |
117 | 117 | ||
118 | static void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { | ||
119 | cairo_set_source_rgba(cairo, | ||
120 | (color >> (3*8) & 0xFF) / 255.0, | ||
121 | (color >> (2*8) & 0xFF) / 255.0, | ||
122 | (color >> (1*8) & 0xFF) / 255.0, | ||
123 | (color >> (0*8) & 0xFF) / 255.0); | ||
124 | } | ||
125 | |||
126 | void render_color(struct window *window, uint32_t color) { | ||
127 | cairo_set_source_u32(window->cairo, color); | ||
128 | cairo_paint(window->cairo); | ||
129 | window_render(window); | ||
130 | } | ||
131 | |||
132 | void render_image(struct window *window, cairo_surface_t *image, enum scaling_mode scaling_mode) { | ||
133 | double width = cairo_image_surface_get_width(image); | ||
134 | double height = cairo_image_surface_get_height(image); | ||
135 | |||
136 | switch (scaling_mode) { | ||
137 | case SCALING_MODE_STRETCH: | ||
138 | cairo_scale(window->cairo, | ||
139 | (double) window->width / width, | ||
140 | (double) window->height / height); | ||
141 | cairo_set_source_surface(window->cairo, image, 0, 0); | ||
142 | break; | ||
143 | case SCALING_MODE_FILL: | ||
144 | { | ||
145 | double window_ratio = (double) window->width / window->height; | ||
146 | double bg_ratio = width / height; | ||
147 | |||
148 | if (window_ratio > bg_ratio) { | ||
149 | double scale = (double) window->width / width; | ||
150 | cairo_scale(window->cairo, scale, scale); | ||
151 | cairo_set_source_surface(window->cairo, image, | ||
152 | 0, | ||
153 | (double) window->height/2 / scale - height/2); | ||
154 | } else { | ||
155 | double scale = (double) window->height / height; | ||
156 | cairo_scale(window->cairo, scale, scale); | ||
157 | cairo_set_source_surface(window->cairo, image, | ||
158 | (double) window->width/2 / scale - width/2, | ||
159 | 0); | ||
160 | } | ||
161 | break; | ||
162 | } | ||
163 | case SCALING_MODE_FIT: | ||
164 | { | ||
165 | double window_ratio = (double) window->width / window->height; | ||
166 | double bg_ratio = width / height; | ||
167 | |||
168 | if (window_ratio > bg_ratio) { | ||
169 | double scale = (double) window->height / height; | ||
170 | cairo_scale(window->cairo, scale, scale); | ||
171 | cairo_set_source_surface(window->cairo, image, | ||
172 | (double) window->width/2 / scale - width/2, | ||
173 | 0); | ||
174 | } else { | ||
175 | double scale = (double) window->width / width; | ||
176 | cairo_scale(window->cairo, scale, scale); | ||
177 | cairo_set_source_surface(window->cairo, image, | ||
178 | 0, | ||
179 | (double) window->height/2 / scale - height/2); | ||
180 | } | ||
181 | break; | ||
182 | } | ||
183 | case SCALING_MODE_CENTER: | ||
184 | cairo_set_source_surface(window->cairo, image, | ||
185 | (double) window->width/2 - width/2, | ||
186 | (double) window->height/2 - height/2); | ||
187 | break; | ||
188 | case SCALING_MODE_TILE: | ||
189 | { | ||
190 | cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); | ||
191 | cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); | ||
192 | cairo_set_source(window->cairo, pattern); | ||
193 | break; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | cairo_paint(window->cairo); | ||
198 | |||
199 | window_render(window); | ||
200 | } | ||
201 | |||
118 | int main(int argc, char **argv) { | 202 | int main(int argc, char **argv) { |
119 | char *image_path = NULL; | 203 | char *image_path = NULL; |
120 | char *scaling_mode_str = "fit"; | 204 | char *scaling_mode_str = "fit"; |
205 | uint32_t color = 0xFFFFFFFF; | ||
121 | 206 | ||
122 | init_log(L_INFO); | 207 | init_log(L_INFO); |
123 | 208 | ||
124 | static struct option long_options[] = { | 209 | static struct option long_options[] = { |
125 | {"help", no_argument, NULL, 'h'}, | 210 | {"help", no_argument, NULL, 'h'}, |
211 | {"color", required_argument, NULL, 'c'}, | ||
126 | {"image", required_argument, NULL, 'i'}, | 212 | {"image", required_argument, NULL, 'i'}, |
127 | {"scaling", required_argument, NULL, 's'}, | 213 | {"scaling", required_argument, NULL, 's'}, |
128 | {"tiling", no_argument, NULL, 't'}, | 214 | {"tiling", no_argument, NULL, 't'}, |
@@ -134,6 +220,7 @@ int main(int argc, char **argv) { | |||
134 | "Usage: swaylock [options...]\n" | 220 | "Usage: swaylock [options...]\n" |
135 | "\n" | 221 | "\n" |
136 | " -h, --help Show help message and quit.\n" | 222 | " -h, --help Show help message and quit.\n" |
223 | " -c, --color <rrggbb> Turn the screen into the given color instead of white.\n" | ||
137 | " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" | 224 | " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" |
138 | " -t, --tiling Same as --scaling=tile.\n" | 225 | " -t, --tiling Same as --scaling=tile.\n" |
139 | " -v, --version Show the version number and quit.\n" | 226 | " -v, --version Show the version number and quit.\n" |
@@ -142,11 +229,21 @@ int main(int argc, char **argv) { | |||
142 | int c; | 229 | int c; |
143 | while (1) { | 230 | while (1) { |
144 | int option_index = 0; | 231 | int option_index = 0; |
145 | c = getopt_long(argc, argv, "hi:s:tv", long_options, &option_index); | 232 | c = getopt_long(argc, argv, "hc:i:s:tv", long_options, &option_index); |
146 | if (c == -1) { | 233 | if (c == -1) { |
147 | break; | 234 | break; |
148 | } | 235 | } |
149 | switch (c) { | 236 | switch (c) { |
237 | case 'c': | ||
238 | if (strlen(optarg) < 6) { | ||
239 | fprintf(stderr, "color must be specified in 3 byte format, e.g. ff0000\n"); | ||
240 | exit(EXIT_FAILURE); | ||
241 | } | ||
242 | color = strtol(optarg, NULL, 16); | ||
243 | color <<= 8; | ||
244 | color |= 0xFF; | ||
245 | sway_log(L_DEBUG, "color: 0x%x", color); | ||
246 | break; | ||
150 | case 'i': | 247 | case 'i': |
151 | image_path = optarg; | 248 | image_path = optarg; |
152 | break; | 249 | break; |
@@ -170,10 +267,19 @@ int main(int argc, char **argv) { | |||
170 | } | 267 | } |
171 | } | 268 | } |
172 | 269 | ||
173 | // TODO: support locking without image | 270 | enum scaling_mode scaling_mode = SCALING_MODE_STRETCH; |
174 | if (!image_path) { | 271 | if (strcmp(scaling_mode_str, "stretch") == 0) { |
175 | fprintf(stderr, "No image specified!\n"); | 272 | scaling_mode = SCALING_MODE_STRETCH; |
176 | exit(EXIT_FAILURE); | 273 | } else if (strcmp(scaling_mode_str, "fill") == 0) { |
274 | scaling_mode = SCALING_MODE_FILL; | ||
275 | } else if (strcmp(scaling_mode_str, "fit") == 0) { | ||
276 | scaling_mode = SCALING_MODE_FIT; | ||
277 | } else if (strcmp(scaling_mode_str, "center") == 0) { | ||
278 | scaling_mode = SCALING_MODE_CENTER; | ||
279 | } else if (strcmp(scaling_mode_str, "tile") == 0) { | ||
280 | scaling_mode = SCALING_MODE_TILE; | ||
281 | } else { | ||
282 | sway_abort("Unsupported scaling mode: %s", scaling_mode_str); | ||
177 | } | 283 | } |
178 | 284 | ||
179 | password = malloc(1024); // TODO: Let this grow | 285 | password = malloc(1024); // TODO: Let this grow |
@@ -197,111 +303,40 @@ int main(int argc, char **argv) { | |||
197 | 303 | ||
198 | registry->input->notify = notify_key; | 304 | registry->input->notify = notify_key; |
199 | 305 | ||
306 | cairo_surface_t *image = NULL; | ||
307 | |||
308 | if (image_path) { | ||
200 | #ifdef WITH_GDK_PIXBUF | 309 | #ifdef WITH_GDK_PIXBUF |
201 | GError *err = NULL; | 310 | GError *err = NULL; |
202 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); | 311 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); |
203 | if (!pixbuf) { | 312 | if (!pixbuf) { |
204 | sway_abort("Failed to load background image."); | 313 | sway_abort("Failed to load background image."); |
205 | } | 314 | } |
206 | cairo_surface_t *image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); | 315 | image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); |
207 | g_object_unref(pixbuf); | 316 | g_object_unref(pixbuf); |
208 | #else | 317 | #else |
209 | cairo_surface_t *image = cairo_image_surface_create_from_png(argv[1]); | 318 | cairo_surface_t *image = cairo_image_surface_create_from_png(argv[1]); |
210 | #endif //WITH_GDK_PIXBUF | 319 | #endif //WITH_GDK_PIXBUF |
211 | if (!image) { | 320 | if (!image) { |
212 | sway_abort("Failed to read background image."); | 321 | sway_abort("Failed to read background image."); |
213 | } | 322 | } |
214 | double width = cairo_image_surface_get_width(image); | ||
215 | double height = cairo_image_surface_get_height(image); | ||
216 | |||
217 | enum scaling_mode scaling_mode = SCALING_MODE_STRETCH; | ||
218 | if (strcmp(scaling_mode_str, "stretch") == 0) { | ||
219 | scaling_mode = SCALING_MODE_STRETCH; | ||
220 | } else if (strcmp(scaling_mode_str, "fill") == 0) { | ||
221 | scaling_mode = SCALING_MODE_FILL; | ||
222 | } else if (strcmp(scaling_mode_str, "fit") == 0) { | ||
223 | scaling_mode = SCALING_MODE_FIT; | ||
224 | } else if (strcmp(scaling_mode_str, "center") == 0) { | ||
225 | scaling_mode = SCALING_MODE_CENTER; | ||
226 | } else if (strcmp(scaling_mode_str, "tile") == 0) { | ||
227 | scaling_mode = SCALING_MODE_TILE; | ||
228 | } else { | ||
229 | sway_abort("Unsupported scaling mode: %s", scaling_mode_str); | ||
230 | } | 323 | } |
231 | 324 | ||
232 | for (i = 0; i < surfaces->length; ++i) { | 325 | for (i = 0; i < surfaces->length; ++i) { |
233 | struct window *window = surfaces->items[i]; | 326 | struct window *window = surfaces->items[i]; |
234 | if (window_prerender(window) && window->cairo) { | 327 | if (!window_prerender(window) || !window->cairo) { |
235 | switch (scaling_mode) { | 328 | continue; |
236 | case SCALING_MODE_STRETCH: | 329 | } |
237 | cairo_scale(window->cairo, | 330 | if (image) { |
238 | (double) window->width / width, | 331 | render_image(window, image, scaling_mode); |
239 | (double) window->height / height); | 332 | } else { |
240 | cairo_set_source_surface(window->cairo, image, 0, 0); | 333 | render_color(window, color); |
241 | break; | ||
242 | case SCALING_MODE_FILL: | ||
243 | { | ||
244 | double window_ratio = (double) window->width / window->height; | ||
245 | double bg_ratio = width / height; | ||
246 | |||
247 | if (window_ratio > bg_ratio) { | ||
248 | double scale = (double) window->width / width; | ||
249 | cairo_scale(window->cairo, scale, scale); | ||
250 | cairo_set_source_surface(window->cairo, image, | ||
251 | 0, | ||
252 | (double) window->height/2 / scale - height/2); | ||
253 | } else { | ||
254 | double scale = (double) window->height / height; | ||
255 | cairo_scale(window->cairo, scale, scale); | ||
256 | cairo_set_source_surface(window->cairo, image, | ||
257 | (double) window->width/2 / scale - width/2, | ||
258 | 0); | ||
259 | } | ||
260 | break; | ||
261 | } | ||
262 | case SCALING_MODE_FIT: | ||
263 | { | ||
264 | double window_ratio = (double) window->width / window->height; | ||
265 | double bg_ratio = width / height; | ||
266 | |||
267 | if (window_ratio > bg_ratio) { | ||
268 | double scale = (double) window->height / height; | ||
269 | cairo_scale(window->cairo, scale, scale); | ||
270 | cairo_set_source_surface(window->cairo, image, | ||
271 | (double) window->width/2 / scale - width/2, | ||
272 | 0); | ||
273 | } else { | ||
274 | double scale = (double) window->width / width; | ||
275 | cairo_scale(window->cairo, scale, scale); | ||
276 | cairo_set_source_surface(window->cairo, image, | ||
277 | 0, | ||
278 | (double) window->height/2 / scale - height/2); | ||
279 | } | ||
280 | break; | ||
281 | } | ||
282 | case SCALING_MODE_CENTER: | ||
283 | cairo_set_source_surface(window->cairo, image, | ||
284 | (double) window->width/2 - width/2, | ||
285 | (double) window->height/2 - height/2); | ||
286 | break; | ||
287 | case SCALING_MODE_TILE: | ||
288 | { | ||
289 | cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); | ||
290 | cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); | ||
291 | cairo_set_source(window->cairo, pattern); | ||
292 | break; | ||
293 | } | ||
294 | default: | ||
295 | sway_abort("Scaling mode '%s' not implemented yet!", scaling_mode_str); | ||
296 | } | ||
297 | |||
298 | cairo_paint(window->cairo); | ||
299 | |||
300 | window_render(window); | ||
301 | } | 334 | } |
302 | } | 335 | } |
303 | 336 | ||
304 | cairo_surface_destroy(image); | 337 | if (image) { |
338 | cairo_surface_destroy(image); | ||
339 | } | ||
305 | 340 | ||
306 | bool locked = false; | 341 | bool locked = false; |
307 | while (wl_display_dispatch(registry->display) != -1) { | 342 | while (wl_display_dispatch(registry->display) != -1) { |