diff options
Diffstat (limited to 'swaynagbar/render.c')
-rw-r--r-- | swaynagbar/render.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/swaynagbar/render.c b/swaynagbar/render.c new file mode 100644 index 00000000..c0f59298 --- /dev/null +++ b/swaynagbar/render.c | |||
@@ -0,0 +1,152 @@ | |||
1 | #include <stdint.h> | ||
2 | #include "cairo.h" | ||
3 | #include "log.h" | ||
4 | #include "pango.h" | ||
5 | #include "pool-buffer.h" | ||
6 | #include "swaynagbar/nagbar.h" | ||
7 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" | ||
8 | |||
9 | static uint32_t render_message(cairo_t *cairo, struct sway_nagbar *nagbar) { | ||
10 | uint32_t height = nagbar->height * nagbar->scale; | ||
11 | height -= NAGBAR_BAR_BORDER_THICKNESS * nagbar->scale; | ||
12 | |||
13 | int text_width, text_height; | ||
14 | get_text_size(cairo, nagbar->font, &text_width, &text_height, | ||
15 | nagbar->scale, true, "%s", nagbar->message); | ||
16 | |||
17 | int padding = NAGBAR_MESSAGE_PADDING * nagbar->scale; | ||
18 | |||
19 | uint32_t ideal_height = text_height + padding * 2; | ||
20 | uint32_t ideal_surface_height = ideal_height / nagbar->scale; | ||
21 | if (nagbar->height < ideal_surface_height) { | ||
22 | return ideal_surface_height; | ||
23 | } | ||
24 | |||
25 | cairo_set_source_u32(cairo, nagbar->colors.text); | ||
26 | cairo_move_to(cairo, padding, (int)(height / 2.0 - text_height / 2.0)); | ||
27 | pango_printf(cairo, nagbar->font, nagbar->scale, true, "%s", | ||
28 | nagbar->message); | ||
29 | |||
30 | return nagbar->height; | ||
31 | } | ||
32 | |||
33 | static uint32_t render_button(cairo_t *cairo, struct sway_nagbar *nagbar, | ||
34 | int button_index, int *x) { | ||
35 | uint32_t height = nagbar->height * nagbar->scale; | ||
36 | height -= NAGBAR_BAR_BORDER_THICKNESS * nagbar->scale; | ||
37 | struct sway_nagbar_button *button = nagbar->buttons->items[button_index]; | ||
38 | |||
39 | int text_width, text_height; | ||
40 | get_text_size(cairo, nagbar->font, &text_width, &text_height, | ||
41 | nagbar->scale, true, "%s", button->text); | ||
42 | |||
43 | int border = NAGBAR_BUTTON_BORDER_THICKNESS * nagbar->scale; | ||
44 | int padding = NAGBAR_BUTTON_PADDING * nagbar->scale; | ||
45 | |||
46 | uint32_t ideal_height = text_height + padding * 2 + border * 2; | ||
47 | uint32_t ideal_surface_height = ideal_height / nagbar->scale; | ||
48 | if (nagbar->height < ideal_surface_height) { | ||
49 | return ideal_surface_height; | ||
50 | } | ||
51 | |||
52 | button->x = *x - border - text_width - padding * 2; | ||
53 | button->y = (int)(height / 2.0 - text_height / 2.0) - padding; | ||
54 | button->width = text_width + padding * 2; | ||
55 | button->height = text_height + padding * 2; | ||
56 | |||
57 | cairo_set_source_u32(cairo, nagbar->colors.border); | ||
58 | cairo_rectangle(cairo, button->x - border, button->y - border, | ||
59 | button->width + border * 2, button->height + border * 2); | ||
60 | cairo_fill(cairo); | ||
61 | |||
62 | cairo_set_source_u32(cairo, nagbar->colors.button_background); | ||
63 | cairo_rectangle(cairo, button->x, button->y, | ||
64 | button->width, button->height); | ||
65 | cairo_fill(cairo); | ||
66 | |||
67 | cairo_set_source_u32(cairo, nagbar->colors.text); | ||
68 | cairo_move_to(cairo, button->x + padding, button->y + padding); | ||
69 | pango_printf(cairo, nagbar->font, nagbar->scale, true, "%s", button->text); | ||
70 | |||
71 | *x = button->x - border; | ||
72 | |||
73 | return nagbar->height; | ||
74 | } | ||
75 | |||
76 | static uint32_t render_to_cairo(cairo_t *cairo, struct sway_nagbar *nagbar) { | ||
77 | uint32_t max_height = 0; | ||
78 | |||
79 | cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); | ||
80 | cairo_set_source_u32(cairo, nagbar->colors.background); | ||
81 | cairo_paint(cairo); | ||
82 | |||
83 | uint32_t h = render_message(cairo, nagbar); | ||
84 | max_height = h > max_height ? h : max_height; | ||
85 | |||
86 | int x = (nagbar->width - NAGBAR_BUTTON_MARGIN_RIGHT) * nagbar->scale; | ||
87 | for (int i = 0; i < nagbar->buttons->length; i++) { | ||
88 | h = render_button(cairo, nagbar, i, &x); | ||
89 | max_height = h > max_height ? h : max_height; | ||
90 | x -= NAGBAR_BUTTON_GAP * nagbar->scale; | ||
91 | if (i == 0) { | ||
92 | x -= NAGBAR_BUTTON_GAP_CLOSE * nagbar->scale; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | int border = NAGBAR_BAR_BORDER_THICKNESS * nagbar->scale; | ||
97 | if (max_height > nagbar->height) { | ||
98 | max_height += border; | ||
99 | } | ||
100 | cairo_set_source_u32(cairo, nagbar->colors.border_bottom); | ||
101 | cairo_rectangle(cairo, 0, nagbar->height * nagbar->scale - border, | ||
102 | nagbar->width * nagbar->scale, border); | ||
103 | cairo_fill(cairo); | ||
104 | |||
105 | return max_height > nagbar->height ? max_height : nagbar->height; | ||
106 | } | ||
107 | |||
108 | void render_frame(struct sway_nagbar *nagbar) { | ||
109 | if (!nagbar->run_display) { | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | cairo_surface_t *recorder = cairo_recording_surface_create( | ||
114 | CAIRO_CONTENT_COLOR_ALPHA, NULL); | ||
115 | cairo_t *cairo = cairo_create(recorder); | ||
116 | cairo_save(cairo); | ||
117 | cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); | ||
118 | cairo_paint(cairo); | ||
119 | cairo_restore(cairo); | ||
120 | uint32_t height = render_to_cairo(cairo, nagbar); | ||
121 | if (height != nagbar->height) { | ||
122 | zwlr_layer_surface_v1_set_size(nagbar->layer_surface, 0, height); | ||
123 | zwlr_layer_surface_v1_set_exclusive_zone(nagbar->layer_surface, | ||
124 | height); | ||
125 | wl_surface_commit(nagbar->surface); | ||
126 | wl_display_roundtrip(nagbar->display); | ||
127 | } else { | ||
128 | nagbar->current_buffer = get_next_buffer(nagbar->shm, | ||
129 | nagbar->buffers, | ||
130 | nagbar->width * nagbar->scale, | ||
131 | nagbar->height * nagbar->scale); | ||
132 | cairo_t *shm = nagbar->current_buffer->cairo; | ||
133 | |||
134 | cairo_save(shm); | ||
135 | cairo_set_operator(shm, CAIRO_OPERATOR_CLEAR); | ||
136 | cairo_paint(shm); | ||
137 | cairo_restore(shm); | ||
138 | |||
139 | cairo_set_source_surface(shm, recorder, 0.0, 0.0); | ||
140 | cairo_paint(shm); | ||
141 | |||
142 | wl_surface_set_buffer_scale(nagbar->surface, nagbar->scale); | ||
143 | wl_surface_attach(nagbar->surface, | ||
144 | nagbar->current_buffer->buffer, 0, 0); | ||
145 | wl_surface_damage(nagbar->surface, 0, 0, | ||
146 | nagbar->width, nagbar->height); | ||
147 | wl_surface_commit(nagbar->surface); | ||
148 | wl_display_roundtrip(nagbar->display); | ||
149 | } | ||
150 | cairo_surface_destroy(recorder); | ||
151 | cairo_destroy(cairo); | ||
152 | } | ||