diff options
Diffstat (limited to 'swaylock/render.c')
-rw-r--r-- | swaylock/render.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/swaylock/render.c b/swaylock/render.c new file mode 100644 index 00000000..cd387be5 --- /dev/null +++ b/swaylock/render.c | |||
@@ -0,0 +1,150 @@ | |||
1 | #define _POSIX_C_SOURCE 199506L | ||
2 | #include <math.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <wayland-client.h> | ||
5 | #include "cairo.h" | ||
6 | #include "background-image.h" | ||
7 | #include "swaylock/swaylock.h" | ||
8 | |||
9 | #define M_PI 3.14159265358979323846 | ||
10 | const int ARC_RADIUS = 50; | ||
11 | const int ARC_THICKNESS = 10; | ||
12 | const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; | ||
13 | const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; | ||
14 | |||
15 | void render_frame(struct swaylock_surface *surface) { | ||
16 | struct swaylock_state *state = surface->state; | ||
17 | |||
18 | int buffer_width = surface->width * surface->scale; | ||
19 | int buffer_height = surface->height * surface->scale; | ||
20 | |||
21 | surface->current_buffer = get_next_buffer(state->shm, | ||
22 | surface->buffers, buffer_width, buffer_height); | ||
23 | cairo_t *cairo = surface->current_buffer->cairo; | ||
24 | cairo_identity_matrix(cairo); | ||
25 | |||
26 | if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { | ||
27 | cairo_set_source_u32(cairo, state->args.color); | ||
28 | cairo_paint(cairo); | ||
29 | } else { | ||
30 | render_background_image(cairo, surface->image, | ||
31 | state->args.mode, buffer_width, buffer_height); | ||
32 | } | ||
33 | cairo_identity_matrix(cairo); | ||
34 | |||
35 | int arc_radius = ARC_RADIUS * surface->scale; | ||
36 | int arc_thickness = ARC_THICKNESS * surface->scale; | ||
37 | float type_indicator_border_thickness = | ||
38 | TYPE_INDICATOR_BORDER_THICKNESS * surface->scale; | ||
39 | |||
40 | if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) { | ||
41 | // Draw circle | ||
42 | cairo_set_line_width(cairo, arc_thickness); | ||
43 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius, 0, 2 * M_PI); | ||
44 | switch (state->auth_state) { | ||
45 | case AUTH_STATE_INPUT: | ||
46 | case AUTH_STATE_BACKSPACE: { | ||
47 | cairo_set_source_rgba(cairo, 0, 0, 0, 0.75); | ||
48 | cairo_fill_preserve(cairo); | ||
49 | cairo_set_source_rgb(cairo, 51.0 / 255, 125.0 / 255, 0); | ||
50 | cairo_stroke(cairo); | ||
51 | } break; | ||
52 | case AUTH_STATE_VALIDATING: { | ||
53 | cairo_set_source_rgba(cairo, 0, 114.0 / 255, 255.0 / 255, 0.75); | ||
54 | cairo_fill_preserve(cairo); | ||
55 | cairo_set_source_rgb(cairo, 51.0 / 255, 0, 250.0 / 255); | ||
56 | cairo_stroke(cairo); | ||
57 | } break; | ||
58 | case AUTH_STATE_INVALID: { | ||
59 | cairo_set_source_rgba(cairo, 250.0 / 255, 0, 0, 0.75); | ||
60 | cairo_fill_preserve(cairo); | ||
61 | cairo_set_source_rgb(cairo, 125.0 / 255, 51.0 / 255, 0); | ||
62 | cairo_stroke(cairo); | ||
63 | } break; | ||
64 | default: break; | ||
65 | } | ||
66 | |||
67 | // Draw a message | ||
68 | char *text = NULL; | ||
69 | cairo_set_source_rgb(cairo, 0, 0, 0); | ||
70 | cairo_select_font_face(cairo, "sans-serif", | ||
71 | CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); | ||
72 | cairo_set_font_size(cairo, arc_radius / 3.0f); | ||
73 | switch (state->auth_state) { | ||
74 | case AUTH_STATE_VALIDATING: | ||
75 | text = "verifying"; | ||
76 | break; | ||
77 | case AUTH_STATE_INVALID: | ||
78 | text = "wrong"; | ||
79 | break; | ||
80 | default: break; | ||
81 | } | ||
82 | |||
83 | if (text) { | ||
84 | cairo_text_extents_t extents; | ||
85 | double x, y; | ||
86 | cairo_text_extents(cairo, text, &extents); | ||
87 | x = (buffer_width / 2) - | ||
88 | (extents.width / 2 + extents.x_bearing); | ||
89 | y = (buffer_height / 2) - | ||
90 | (extents.height / 2 + extents.y_bearing); | ||
91 | |||
92 | cairo_move_to(cairo, x, y); | ||
93 | cairo_show_text(cairo, text); | ||
94 | cairo_close_path(cairo); | ||
95 | cairo_new_sub_path(cairo); | ||
96 | } | ||
97 | |||
98 | // Typing indicator: Highlight random part on keypress | ||
99 | if (state->auth_state == AUTH_STATE_INPUT | ||
100 | || state->auth_state == AUTH_STATE_BACKSPACE) { | ||
101 | static double highlight_start = 0; | ||
102 | highlight_start += | ||
103 | (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; | ||
104 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | ||
105 | arc_radius, highlight_start, | ||
106 | highlight_start + TYPE_INDICATOR_RANGE); | ||
107 | if (state->auth_state == AUTH_STATE_INPUT) { | ||
108 | cairo_set_source_rgb(cairo, 51.0 / 255, 219.0 / 255, 0); | ||
109 | } else { | ||
110 | cairo_set_source_rgb(cairo, 219.0 / 255, 51.0 / 255, 0); | ||
111 | } | ||
112 | cairo_stroke(cairo); | ||
113 | |||
114 | // Draw borders | ||
115 | cairo_set_source_rgb(cairo, 0, 0, 0); | ||
116 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | ||
117 | arc_radius, highlight_start, | ||
118 | highlight_start + type_indicator_border_thickness); | ||
119 | cairo_stroke(cairo); | ||
120 | |||
121 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | ||
122 | arc_radius, highlight_start + TYPE_INDICATOR_RANGE, | ||
123 | highlight_start + TYPE_INDICATOR_RANGE + | ||
124 | type_indicator_border_thickness); | ||
125 | cairo_stroke(cairo); | ||
126 | } | ||
127 | |||
128 | // Draw inner + outer border of the circle | ||
129 | cairo_set_source_rgb(cairo, 0, 0, 0); | ||
130 | cairo_set_line_width(cairo, 2.0 * surface->scale); | ||
131 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | ||
132 | arc_radius - arc_thickness / 2, 0, 2 * M_PI); | ||
133 | cairo_stroke(cairo); | ||
134 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | ||
135 | arc_radius + arc_thickness / 2, 0, 2 * M_PI); | ||
136 | cairo_stroke(cairo); | ||
137 | } | ||
138 | |||
139 | wl_surface_set_buffer_scale(surface->surface, surface->scale); | ||
140 | wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); | ||
141 | wl_surface_damage(surface->surface, 0, 0, surface->width, surface->height); | ||
142 | wl_surface_commit(surface->surface); | ||
143 | } | ||
144 | |||
145 | void render_frames(struct swaylock_state *state) { | ||
146 | struct swaylock_surface *surface; | ||
147 | wl_list_for_each(surface, &state->surfaces, link) { | ||
148 | render_frame(surface); | ||
149 | } | ||
150 | } | ||