summaryrefslogtreecommitdiff
path: root/extras.c
diff options
context:
space:
mode:
Diffstat (limited to 'extras.c')
-rw-r--r--extras.c448
1 files changed, 448 insertions, 0 deletions
diff --git a/extras.c b/extras.c
new file mode 100644
index 0000000..37819f5
--- /dev/null
+++ b/extras.c
@@ -0,0 +1,448 @@
1/*
2 * This file is part of i3lock-extended
3 * Copyright (C) 2020 Simeon Simeonov
4
5 * i3lock-extended is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9
10 * i3lock-extended is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdint.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <cairo.h>
25
26#include <xcb/xcb.h>
27#include <xcb/xcb_aux.h>
28#include <xcb/randr.h>
29
30#include "randr.h"
31#include "extras.h"
32
33
34extern int failed_attempts;
35
36
37static void i3lock_color_to_array(double *rgb16, const char *color) {
38
39 char strgroups[3][3] = {{color[0], color[1], '\0'},
40 {color[2], color[3], '\0'},
41 {color[4], color[5], '\0'}};
42 *rgb16 = strtol(strgroups[0], NULL, 16) / 255.0;
43 *(rgb16 + 1) = strtol(strgroups[1], NULL, 16) / 255.0;
44 *(rgb16 + 2) = strtol(strgroups[2], NULL, 16) / 255.0;
45
46}
47
48
49static void i3clock_fetch_digital_clock_xy(int *x,
50 int *y,
51 const i3lock_digital_clock_t *dc,
52 const uint32_t *resolution,
53 int text_length) {
54
55 /* x */
56 if (dc->horizontal_alignment == I3LOCK_ALIGN_CENTER) {
57 *x = resolution[0] / 2 - text_length * dc->text_size / 2;
58 } else if (dc->horizontal_alignment == I3LOCK_ALIGN_RIGHT) {
59 *x = resolution[0] - resolution[0] / 10 - text_length * dc->text_size;
60 } else {
61 /* left */
62 *x = resolution[0] / 10; /* 10% */
63 }
64
65 /* y */
66 if (dc->vertical_alignment == I3LOCK_ALIGN_MIDDLE) {
67 *y = resolution[1] / 2 - dc->text_size / 2;
68 } else if (dc->vertical_alignment == I3LOCK_ALIGN_BOTTOM) {
69 *y = resolution[1] - resolution[1] / 10 - dc->text_size;
70 } else {
71 /* top */
72 *y = resolution[1] / 10; /* 10% */
73 }
74
75}
76
77
78static void i3clock_fetch_led_clock_xy(int *x,
79 int *y,
80 const i3lock_led_clock_t *lc,
81 const uint32_t *resolution) {
82 int clock_length, clock_height;
83
84 /* x */
85 clock_length = 6 * resolution[1] / I3LOCK_SCALE_LED_SPACING + \
86 5 * resolution[1] / I3LOCK_SCALE_LED_LENGTH;
87 if (lc->horizontal_alignment == I3LOCK_ALIGN_CENTER) {
88 *x = resolution[0] / 2 - clock_length / 2;
89 } else if (lc->horizontal_alignment == I3LOCK_ALIGN_RIGHT) {
90 *x = resolution[0] - resolution[0] / 10 - clock_length;
91 } else {
92 /* left */
93 *x = resolution[0] / 10; /* 10% */
94 }
95
96 /* y */
97 clock_height = 3 * resolution[1] / I3LOCK_SCALE_LED_SPACING + \
98 2 * resolution[1] / I3LOCK_SCALE_LED_LENGTH;
99 if (lc->vertical_alignment == I3LOCK_ALIGN_MIDDLE) {
100 *y = resolution[1] / 2 - clock_height / 2;
101 } else if (lc->vertical_alignment == I3LOCK_ALIGN_BOTTOM) {
102 *y = resolution[1] - resolution[1] / 10 - clock_height;
103 } else {
104 /* top */
105 *y = resolution[1] / 10; /* 10% */
106 }
107
108}
109
110
111static void i3lock_draw_led(cairo_t *cr,
112 double x,
113 double y,
114 double length,
115 int type,
116 const i3lock_led_clock_t *lc) {
117 double border_color[3], face_color[3];
118 i3lock_color_to_array(border_color, lc->led_border_color);
119 if (type) {
120 /* LED on */
121 i3lock_color_to_array(face_color, lc->led_on_color);
122 } else {
123 i3lock_color_to_array(face_color, lc->led_off_color);
124 }
125 cairo_set_line_width(cr, 2);
126 cairo_rectangle(cr, x, y, length, length);
127 cairo_set_source_rgb(cr, face_color[0], face_color[1], face_color[2]);
128 cairo_fill(cr);
129 cairo_rectangle(cr, x, y, length, length);
130 cairo_set_source_rgb(cr, border_color[0], border_color[1], border_color[2]);
131 cairo_stroke(cr);
132}
133
134
135void i3lock_draw_digital_clock(cairo_t *cr,
136 const i3lock_digital_clock_t *dc,
137 const uint32_t *resolution,
138 const struct tm *brokentime) {
139 double rgb16[3];
140 char current_time_str[128];
141 int x, y;
142 strftime(current_time_str,
143 128,
144 dc->template,
145 brokentime);
146 i3lock_color_to_array(rgb16, dc->color);
147 cairo_set_source_rgb(cr,
148 rgb16[0],
149 rgb16[1],
150 rgb16[2]);
151 cairo_set_font_size(cr, dc->text_size);
152 if (xr_screens > 0) {
153 /* xinerama */
154 int screen;
155 uint32_t screen_resolution[2];
156 for (screen = 0; screen < xr_screens; ++screen) {
157 screen_resolution[0] = xr_resolutions[screen].width;
158 screen_resolution[1] = xr_resolutions[screen].height;
159 i3clock_fetch_digital_clock_xy(&x,
160 &y,
161 dc,
162 screen_resolution,
163 strlen(current_time_str));
164 cairo_move_to(cr,
165 x + xr_resolutions[screen].x,
166 y + xr_resolutions[screen].y);
167 cairo_show_text(cr, current_time_str);
168 }
169 return;
170 }
171
172 i3clock_fetch_digital_clock_xy(&x,
173 &y,
174 dc,
175 resolution,
176 strlen(current_time_str));
177 /* printf("%dx%d\n", *resolution, *(resolution + 1)); */
178 cairo_move_to(cr, x, y);
179 cairo_show_text(cr, current_time_str);
180
181}
182
183
184void i3lock_draw_string(cairo_t *cr,
185 const char *formatted_string,
186 const i3lock_elapsed_time_t *et,
187 const uint32_t *resolution) {
188 double rgb16[3];
189 int x, y;
190
191 /* create a dummy i3lock_digital_clock_t structure in order to reuse
192 i3clock_fetch_digital_clock_xy */
193 i3lock_digital_clock_t dc = {et->text_size,
194 "",
195 "",
196 et->horizontal_alignment,
197 et->vertical_alignment};
198 i3lock_color_to_array(rgb16, et->color);
199 cairo_set_source_rgb(cr,
200 rgb16[0],
201 rgb16[1],
202 rgb16[2]);
203 cairo_set_font_size(cr, et->text_size);
204 if (xr_screens > 0) {
205 /* xinerama */
206 int screen;
207 uint32_t screen_resolution[2];
208 for (screen = 0; screen < xr_screens; ++screen) {
209 screen_resolution[0] = xr_resolutions[screen].width;
210 screen_resolution[1] = xr_resolutions[screen].height;
211 i3clock_fetch_digital_clock_xy(&x,
212 &y,
213 &dc,
214 screen_resolution,
215 strlen(formatted_string));
216 cairo_move_to(cr,
217 x + xr_resolutions[screen].x,
218 y + xr_resolutions[screen].y);
219 cairo_show_text(cr, formatted_string);
220 }
221 return;
222 }
223
224 i3clock_fetch_digital_clock_xy(&x,
225 &y,
226 &dc,
227 resolution,
228 strlen(formatted_string));
229 /* printf("%dx%d\n", *resolution, *(resolution + 1)); */
230 cairo_move_to(cr, x, y);
231 cairo_show_text(cr, formatted_string);
232
233}
234
235
236void i3lock_draw_elapsed_time(cairo_t *cr,
237 const i3lock_elapsed_time_t *et,
238 const uint32_t *resolution,
239 const time_t *now) {
240 double rgb16[3];
241 char elapsed_time_str[128];
242 int x, y, seconds, minutes, hours, diff_seconds;
243
244 /* create a dummy i3lock_digital_clock_t structure in ordet to reuse
245 i3clock_fetch_digital_clock_xy */
246 i3lock_digital_clock_t dc = {et->text_size,
247 "",
248 "",
249 et->horizontal_alignment,
250 et->vertical_alignment};
251
252 diff_seconds = (int) difftime(*now, et->start_time);
253 hours = diff_seconds / 3600;
254 minutes = (diff_seconds - hours * 3600) / 60;
255 seconds = diff_seconds - hours * 3600 - minutes * 60;
256 if (hours) {
257 snprintf(elapsed_time_str,
258 128,
259 "%d:%02d:%02d",
260 hours,
261 minutes,
262 seconds);
263 } else {
264 snprintf(elapsed_time_str, 128, "%02d:%02d", minutes, seconds);
265 }
266 if (failed_attempts) {
267 char failed_attempts_str[16]; /* ... that many attempts */
268 snprintf(failed_attempts_str,
269 16,
270 " (%d)",
271 failed_attempts);
272 strncat(elapsed_time_str, failed_attempts_str, 16);
273 }
274 i3lock_color_to_array(rgb16, et->color);
275 cairo_set_source_rgb(cr,
276 rgb16[0],
277 rgb16[1],
278 rgb16[2]);
279 cairo_set_font_size(cr, et->text_size);
280 if (xr_screens > 0) {
281 /* xinerama */
282 int screen;
283 uint32_t screen_resolution[2];
284 for (screen = 0; screen < xr_screens; ++screen) {
285 screen_resolution[0] = xr_resolutions[screen].width;
286 screen_resolution[1] = xr_resolutions[screen].height;
287 i3clock_fetch_digital_clock_xy(&x,
288 &y,
289 &dc,
290 screen_resolution,
291 strlen(elapsed_time_str));
292 cairo_move_to(cr,
293 x + xr_resolutions[screen].x,
294 y + xr_resolutions[screen].y);
295 cairo_show_text(cr, elapsed_time_str);
296 }
297 return;
298 }
299
300 i3clock_fetch_digital_clock_xy(&x,
301 &y,
302 &dc,
303 resolution,
304 strlen(elapsed_time_str));
305 /* printf("%dx%d\n", *resolution, *(resolution + 1)); */
306 cairo_move_to(cr, x, y);
307 cairo_show_text(cr, elapsed_time_str);
308
309}
310
311
312void i3lock_draw_led_clock(cairo_t *cr,
313 const i3lock_led_clock_t *lc,
314 const uint32_t *resolution,
315 const struct tm *brokentime) {
316 int side_length, space_length, base_x, base_y;
317 int base_x_h; /* used to make the code more readable */
318 if (xr_screens > 0) {
319 /* xinerama */
320 int screen;
321 uint32_t screen_resolution[2];
322 for (screen = 0; screen < xr_screens; ++screen) {
323 screen_resolution[0] = xr_resolutions[screen].width;
324 screen_resolution[1] = xr_resolutions[screen].height;
325 side_length = xr_resolutions[screen].height / I3LOCK_SCALE_LED_SPACING;
326 space_length = xr_resolutions[screen].height / I3LOCK_SCALE_LED_LENGTH;
327 i3clock_fetch_led_clock_xy(&base_x,
328 &base_y,
329 lc,
330 screen_resolution);
331 base_x += xr_resolutions[screen].x;
332 base_y += xr_resolutions[screen].y;
333 base_x_h = base_x + space_length / 2 + side_length / 2;
334
335 /* hours */
336 i3lock_draw_led(cr,
337 base_x_h,
338 base_y,
339 side_length,
340 brokentime->tm_hour & 16,
341 lc);
342 i3lock_draw_led(cr,
343 base_x_h + space_length + side_length,
344 base_y,
345 side_length,
346 brokentime->tm_hour & 8,
347 lc);
348 i3lock_draw_led(cr,
349 base_x_h + 2 * (space_length + side_length),
350 base_y,
351 side_length,
352 brokentime->tm_hour & 4,
353 lc);
354 i3lock_draw_led(cr,
355 base_x_h + 3 * (space_length + side_length),
356 base_y,
357 side_length,
358 brokentime->tm_hour & 2,
359 lc);
360 i3lock_draw_led(cr,
361 base_x_h + 4 * (space_length + side_length),
362 base_y,
363 side_length,
364 brokentime->tm_hour & 1,
365 lc);
366
367 /* minutes */
368 i3lock_draw_led(cr,
369 base_x,
370 base_y + side_length + space_length,
371 side_length,
372 brokentime->tm_min & 32,
373 lc);
374 i3lock_draw_led(cr,
375 base_x + side_length + space_length,
376 base_y + side_length + space_length,
377 side_length,
378 brokentime->tm_min & 16,
379 lc);
380 i3lock_draw_led(cr,
381 base_x + 2 * (side_length + space_length),
382 base_y + side_length + space_length,
383 side_length,
384 brokentime->tm_min & 8,
385 lc);
386 i3lock_draw_led(cr,
387 base_x + 3 * (side_length + space_length),
388 base_y + side_length + space_length,
389 side_length,
390 brokentime->tm_min & 4,
391 lc);
392 i3lock_draw_led(cr,
393 base_x + 4 * (side_length + space_length),
394 base_y + side_length + space_length,
395 side_length,
396 brokentime->tm_min & 2,
397 lc);
398 i3lock_draw_led(cr,
399 base_x + 5 * (side_length + space_length),
400 base_y + side_length + space_length,
401 side_length,
402 brokentime->tm_min & 1,
403 lc);
404
405 /* seconds */
406 i3lock_draw_led(cr,
407 base_x,
408 base_y + 2 * (side_length + space_length),
409 side_length,
410 brokentime->tm_sec & 32,
411 lc);
412 i3lock_draw_led(cr,
413 base_x + side_length + space_length,
414 base_y + 2 * (side_length + space_length),
415 side_length,
416 brokentime->tm_sec & 16,
417 lc);
418 i3lock_draw_led(cr,
419 base_x + 2 * (side_length + space_length),
420 base_y + 2 * (side_length + space_length),
421 side_length,
422 brokentime->tm_sec & 8,
423 lc);
424 i3lock_draw_led(cr,
425 base_x + 3 * (side_length + space_length),
426 base_y + 2 * (side_length + space_length),
427 side_length,
428 brokentime->tm_sec & 4,
429 lc);
430 i3lock_draw_led(cr,
431 base_x + 4 * (side_length + space_length),
432 base_y + 2 * (side_length + space_length),
433 side_length,
434 brokentime->tm_sec & 2,
435 lc);
436 i3lock_draw_led(cr,
437 base_x + 5 * (side_length + space_length),
438 base_y + 2 * (side_length + space_length),
439 side_length,
440 brokentime->tm_sec & 1,
441 lc);
442 }
443 return;
444 }
445
446}
447
448