1 #include <hikari/renderer.h>
2
3 #include <assert.h>
4
5 #include <hikari/color.h>
6 #include <hikari/geometry.h>
7 #include <hikari/output.h>
8 #include <hikari/renderer.h>
9 #include <hikari/view.h>
10
11 #ifdef HAVE_XWAYLAND
12 #include <hikari/xwayland_unmanaged_view.h>
13 #include <hikari/xwayland_view.h>
14 #endif
15
16 #include <wlr/backend.h>
17 #include <wlr/render/wlr_renderer.h>
18 #include <wlr/types/wlr_matrix.h>
19 #include <wlr/types/wlr_output.h>
20 #include <wlr/types/wlr_output_damage.h>
21 #include <wlr/util/region.h>
22
23 #ifdef HAVE_XWAYLAND
24 #include <wlr/xwayland.h>
25 #endif
26
27 static inline void
renderer_scissor(struct wlr_output * wlr_output,struct wlr_renderer * renderer,pixman_box32_t * rect)28 renderer_scissor(struct wlr_output *wlr_output,
29 struct wlr_renderer *renderer,
30 pixman_box32_t *rect)
31 {
32 assert(wlr_output != NULL);
33
34 struct wlr_box box = { .x = rect->x1,
35 .y = rect->y1,
36 .width = rect->x2 - rect->x1,
37 .height = rect->y2 - rect->y1 };
38
39 wlr_renderer_scissor(renderer, &box);
40 }
41
42 static inline void
rect_render(float color[static4],struct wlr_box * box,struct hikari_renderer * renderer)43 rect_render(float color[static 4],
44 struct wlr_box *box,
45 struct hikari_renderer *renderer)
46 {
47 pixman_region32_t damage;
48 pixman_region32_init(&damage);
49 pixman_region32_union_rect(
50 &damage, &damage, box->x, box->y, box->width, box->height);
51
52 pixman_region32_intersect(&damage, &damage, renderer->damage);
53 bool damaged = pixman_region32_not_empty(&damage);
54 if (!damaged) {
55 goto buffer_damage_finish;
56 }
57
58 struct wlr_renderer *wlr_renderer = renderer->wlr_renderer;
59 struct wlr_output *wlr_output = renderer->wlr_output;
60 assert(renderer);
61
62 float matrix[9];
63 wlr_matrix_project_box(
64 matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, wlr_output->transform_matrix);
65
66 int nrects;
67 pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
68 for (int i = 0; i < nrects; i++) {
69 renderer_scissor(wlr_output, wlr_renderer, &rects[i]);
70 wlr_render_quad_with_matrix(wlr_renderer, color, matrix);
71 }
72
73 buffer_damage_finish:
74 pixman_region32_fini(&damage);
75 }
76
77 static inline void
render_border(struct hikari_border * border,struct hikari_renderer * renderer)78 render_border(struct hikari_border *border, struct hikari_renderer *renderer)
79 {
80 if (border->state == HIKARI_BORDER_NONE) {
81 return;
82 }
83
84 struct wlr_box *geometry = &border->geometry;
85
86 pixman_region32_t damage;
87 pixman_region32_init(&damage);
88 pixman_region32_union_rect(&damage,
89 &damage,
90 geometry->x,
91 geometry->y,
92 geometry->width,
93 geometry->height);
94 pixman_region32_intersect(&damage, &damage, renderer->damage);
95
96 bool damaged = pixman_region32_not_empty(&damage);
97 if (!damaged) {
98 goto buffer_damage_finish;
99 }
100
101 float *color;
102 switch (border->state) {
103 case HIKARI_BORDER_INACTIVE:
104 color = hikari_configuration->border_inactive;
105 break;
106
107 case HIKARI_BORDER_ACTIVE:
108 color = hikari_configuration->border_active;
109 break;
110
111 default:
112 goto buffer_damage_finish;
113 }
114
115 struct wlr_renderer *wlr_renderer = renderer->wlr_renderer;
116 struct wlr_output *wlr_output = renderer->wlr_output;
117 assert(renderer);
118
119 float matrix[9];
120 wlr_matrix_project_box(matrix,
121 geometry,
122 WL_OUTPUT_TRANSFORM_NORMAL,
123 0,
124 wlr_output->transform_matrix);
125
126 int nrects;
127 pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
128 for (int i = 0; i < nrects; i++) {
129 renderer_scissor(wlr_output, wlr_renderer, &rects[i]);
130 rect_render(color, &border->top, renderer);
131 rect_render(color, &border->bottom, renderer);
132 rect_render(color, &border->left, renderer);
133 rect_render(color, &border->right, renderer);
134 }
135
136 buffer_damage_finish:
137 pixman_region32_fini(&damage);
138 }
139
140 static void
render_indicator_bar(struct hikari_indicator_bar * indicator_bar,struct hikari_renderer * renderer)141 render_indicator_bar(struct hikari_indicator_bar *indicator_bar,
142 struct hikari_renderer *renderer)
143 {
144 if (indicator_bar->texture == NULL) {
145 return;
146 }
147
148 struct wlr_box *geometry = renderer->geometry;
149 struct wlr_renderer *wlr_renderer = renderer->wlr_renderer;
150 struct wlr_output *wlr_output = renderer->wlr_output;
151
152 float matrix[9];
153
154 geometry->width = indicator_bar->width;
155 geometry->height = hikari_configuration->font.height;
156
157 wlr_renderer_scissor(wlr_renderer, geometry);
158 wlr_matrix_project_box(matrix, geometry, 0, 0, wlr_output->transform_matrix);
159
160 wlr_render_texture_with_matrix(
161 wlr_renderer, indicator_bar->texture, matrix, 1);
162 }
163
164 static inline void
render_indicator(struct hikari_indicator * indicator,struct hikari_renderer * renderer)165 render_indicator(
166 struct hikari_indicator *indicator, struct hikari_renderer *renderer)
167 {
168 struct wlr_box *border_geometry = renderer->geometry;
169 struct wlr_box geometry = *border_geometry;
170
171 renderer->geometry = &geometry;
172
173 geometry.x += 5;
174
175 struct hikari_indicator_bar *title_bar = &indicator->title;
176 geometry.y += 5;
177 render_indicator_bar(title_bar, renderer);
178
179 int bar_height = hikari_configuration->font.height;
180
181 struct hikari_indicator_bar *sheet_bar = &indicator->sheet;
182 geometry.y += bar_height + 5;
183 render_indicator_bar(sheet_bar, renderer);
184
185 struct hikari_indicator_bar *group_bar = &indicator->group;
186 geometry.y += bar_height + 5;
187 render_indicator_bar(group_bar, renderer);
188
189 struct hikari_indicator_bar *mark_bar = &indicator->mark;
190 geometry.y += bar_height + 5;
191 render_indicator_bar(mark_bar, renderer);
192
193 renderer->geometry = border_geometry;
194 }
195
196 static inline void
render_indicator_frame(struct hikari_indicator_frame * indicator_frame,float color[static4],struct hikari_renderer * renderer)197 render_indicator_frame(struct hikari_indicator_frame *indicator_frame,
198 float color[static 4],
199 struct hikari_renderer *renderer)
200 {
201 struct wlr_box *box = renderer->geometry;
202
203 pixman_region32_t damage;
204 pixman_region32_init(&damage);
205 pixman_region32_union_rect(
206 &damage, &damage, box->x, box->y, box->width, box->height);
207
208 pixman_region32_intersect(&damage, &damage, renderer->damage);
209 bool damaged = pixman_region32_not_empty(&damage);
210 if (!damaged) {
211 goto buffer_damage_finish;
212 }
213
214 struct wlr_renderer *wlr_renderer = renderer->wlr_renderer;
215 struct wlr_output *wlr_output = renderer->wlr_output;
216
217 float top_matrix[9];
218 float bottom_matrix[9];
219 float left_matrix[9];
220 float right_matrix[9];
221
222 wlr_matrix_project_box(top_matrix,
223 &indicator_frame->top,
224 WL_OUTPUT_TRANSFORM_NORMAL,
225 0,
226 wlr_output->transform_matrix);
227
228 wlr_matrix_project_box(bottom_matrix,
229 &indicator_frame->bottom,
230 WL_OUTPUT_TRANSFORM_NORMAL,
231 0,
232 wlr_output->transform_matrix);
233
234 wlr_matrix_project_box(left_matrix,
235 &indicator_frame->left,
236 WL_OUTPUT_TRANSFORM_NORMAL,
237 0,
238 wlr_output->transform_matrix);
239
240 wlr_matrix_project_box(right_matrix,
241 &indicator_frame->right,
242 WL_OUTPUT_TRANSFORM_NORMAL,
243 0,
244 wlr_output->transform_matrix);
245
246 int nrects;
247 pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
248 for (int i = 0; i < nrects; i++) {
249 renderer_scissor(wlr_output, wlr_renderer, &rects[i]);
250 wlr_render_quad_with_matrix(wlr_renderer, color, top_matrix);
251 wlr_render_quad_with_matrix(wlr_renderer, color, bottom_matrix);
252 wlr_render_quad_with_matrix(wlr_renderer, color, left_matrix);
253 wlr_render_quad_with_matrix(wlr_renderer, color, right_matrix);
254 }
255
256 buffer_damage_finish:
257 pixman_region32_fini(&damage);
258 }
259
260 static inline void
clear_output(struct hikari_renderer * renderer)261 clear_output(struct hikari_renderer *renderer)
262 {
263 float *clear_color = hikari_configuration->clear;
264 struct wlr_renderer *wlr_renderer = renderer->wlr_renderer;
265 struct wlr_output *wlr_output = renderer->wlr_output;
266 pixman_region32_t *damage = renderer->damage;
267
268 #ifndef NDEBUG
269 if (hikari_server.track_damage) {
270 float damage_color[4];
271 hikari_color_convert(damage_color, 0x000000);
272 wlr_renderer_clear(wlr_renderer, damage_color);
273 }
274 #endif
275
276 int nrects;
277 pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects);
278 for (int i = 0; i < nrects; ++i) {
279 renderer_scissor(wlr_output, wlr_renderer, &rects[i]);
280 wlr_renderer_clear(wlr_renderer, clear_color);
281 }
282 }
283
284 static inline void
renderer_end(struct hikari_output * output,struct hikari_renderer * renderer)285 renderer_end(struct hikari_output *output, struct hikari_renderer *renderer)
286 {
287 struct wlr_renderer *wlr_renderer = renderer->wlr_renderer;
288 struct wlr_output *wlr_output = renderer->wlr_output;
289
290 wlr_renderer_scissor(wlr_renderer, NULL);
291 wlr_output_render_software_cursors(wlr_output, NULL);
292 wlr_renderer_end(wlr_renderer);
293
294 int width, height;
295 wlr_output_transformed_resolution(wlr_output, &width, &height);
296
297 pixman_region32_t frame_damage;
298 pixman_region32_init(&frame_damage);
299
300 enum wl_output_transform transform =
301 wlr_output_transform_invert(wlr_output->transform);
302 wlr_region_transform(
303 &frame_damage, &output->damage->current, transform, width, height);
304
305 wlr_output_set_damage(wlr_output, &frame_damage);
306 pixman_region32_fini(&frame_damage);
307
308 wlr_output_commit(wlr_output);
309 }
310
311 static inline void
render_texture(struct wlr_texture * texture,struct wlr_output * output,pixman_region32_t * damage,struct wlr_renderer * renderer,const float matrix[static9],struct wlr_box * box,float alpha)312 render_texture(struct wlr_texture *texture,
313 struct wlr_output *output,
314 pixman_region32_t *damage,
315 struct wlr_renderer *renderer,
316 const float matrix[static 9],
317 struct wlr_box *box,
318 float alpha)
319 {
320 pixman_region32_t local_damage;
321 pixman_region32_init(&local_damage);
322 pixman_region32_union_rect(
323 &local_damage, &local_damage, box->x, box->y, box->width, box->height);
324
325 pixman_region32_intersect(&local_damage, &local_damage, damage);
326
327 bool damaged = pixman_region32_not_empty(&local_damage);
328 if (!damaged) {
329 goto damage_finish;
330 }
331
332 int nrects;
333 pixman_box32_t *rects = pixman_region32_rectangles(&local_damage, &nrects);
334 for (int i = 0; i < nrects; ++i) {
335 renderer_scissor(output, renderer, &rects[i]);
336 wlr_render_texture_with_matrix(renderer, texture, matrix, alpha);
337 }
338
339 damage_finish:
340 pixman_region32_fini(&local_damage);
341 }
342
343 static void
render_surface(struct wlr_surface * surface,int sx,int sy,void * data)344 render_surface(struct wlr_surface *surface, int sx, int sy, void *data)
345 {
346 assert(surface != NULL);
347
348 struct wlr_texture *texture = wlr_surface_get_texture(surface);
349
350 if (texture == NULL) {
351 return;
352 }
353
354 struct hikari_renderer *renderer = data;
355 struct wlr_box *geometry = renderer->geometry;
356 struct wlr_output *wlr_output = renderer->wlr_output;
357 struct wlr_renderer *wlr_renderer = renderer->wlr_renderer;
358
359 double ox = geometry->x + sx;
360 double oy = geometry->y + sy;
361
362 struct wlr_box box = { .x = ox * wlr_output->scale,
363 .y = oy * wlr_output->scale,
364 .width = surface->current.width * wlr_output->scale,
365 .height = surface->current.height * wlr_output->scale };
366
367 float matrix[9];
368 enum wl_output_transform transform =
369 wlr_output_transform_invert(surface->current.transform);
370
371 wlr_matrix_project_box(
372 matrix, &box, transform, 0, wlr_output->transform_matrix);
373
374 render_texture(
375 texture, wlr_output, renderer->damage, wlr_renderer, matrix, &box, 1);
376 }
377
378 static inline void
render_background(struct hikari_renderer * renderer,float alpha)379 render_background(struct hikari_renderer *renderer, float alpha)
380 {
381 struct hikari_output *output = renderer->wlr_output->data;
382
383 if (output->background == NULL) {
384 return;
385 }
386
387 float matrix[9];
388 struct wlr_output *wlr_output = output->wlr_output;
389 struct wlr_renderer *wlr_renderer = renderer->wlr_renderer;
390
391 struct wlr_box geometry = { .x = 0, .y = 0 };
392 wlr_output_transformed_resolution(
393 wlr_output, &geometry.width, &geometry.height);
394
395 wlr_matrix_project_box(matrix, &geometry, 0, 0, wlr_output->transform_matrix);
396
397 render_texture(output->background,
398 wlr_output,
399 renderer->damage,
400 wlr_renderer,
401 matrix,
402 &geometry,
403 alpha);
404 }
405
406 #ifdef HAVE_LAYERSHELL
407 static inline void
render_layer(struct wl_list * layers,struct hikari_renderer * renderer)408 render_layer(struct wl_list *layers, struct hikari_renderer *renderer)
409 {
410 struct hikari_layer *layer;
411 wl_list_for_each (layer, layers, layer_surfaces) {
412 renderer->geometry = &layer->geometry;
413 wlr_layer_surface_v1_for_each_surface(
414 layer->surface, render_surface, renderer);
415 }
416 }
417 #endif
418
419 static inline void
render_view(struct hikari_renderer * renderer,struct hikari_view * view)420 render_view(struct hikari_renderer *renderer, struct hikari_view *view)
421 {
422 renderer->geometry = hikari_view_border_geometry(view);
423
424 if (hikari_view_wants_border(view)) {
425 render_border(&view->border, renderer);
426 }
427
428 renderer->geometry = hikari_view_geometry(view);
429
430 hikari_node_for_each_surface(
431 (struct hikari_node *)view, render_surface, renderer);
432 }
433
434 #ifdef HAVE_XWAYLAND
435 static inline void
render_unmanaged_views(struct hikari_renderer * renderer)436 render_unmanaged_views(struct hikari_renderer *renderer)
437 {
438 struct hikari_output *output = renderer->wlr_output->data;
439
440 struct hikari_xwayland_unmanaged_view *xwayland_unmanaged_view;
441 wl_list_for_each_reverse (xwayland_unmanaged_view,
442 &output->unmanaged_xwayland_views,
443 unmanaged_output_views) {
444
445 renderer->geometry = &xwayland_unmanaged_view->geometry;
446
447 wlr_surface_for_each_surface(
448 xwayland_unmanaged_view->surface->surface, render_surface, renderer);
449 }
450 }
451 #endif
452
453 static inline void
render_workspace(struct hikari_renderer * renderer)454 render_workspace(struct hikari_renderer *renderer)
455 {
456 struct hikari_output *output = renderer->wlr_output->data;
457
458 #ifdef HAVE_LAYERSHELL
459 render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], renderer);
460 render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], renderer);
461 #endif
462
463 struct hikari_view *view;
464 wl_list_for_each_reverse (view, &output->workspace->views, workspace_views) {
465 render_view(renderer, view);
466 }
467
468 #ifdef HAVE_LAYERSHELL
469 render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], renderer);
470 #endif
471
472 #ifdef HAVE_XWAYLAND
473 render_unmanaged_views(renderer);
474 #endif
475 }
476
477 #ifdef HAVE_LAYERSHELL
478 static inline void
render_overlay(struct hikari_renderer * renderer)479 render_overlay(struct hikari_renderer *renderer)
480 {
481 struct hikari_output *output = renderer->wlr_output->data;
482 render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], renderer);
483 }
484 #endif
485
486 static inline void
render_output(struct hikari_output * output,pixman_region32_t * damage)487 render_output(struct hikari_output *output, pixman_region32_t *damage)
488 {
489 struct wlr_output *wlr_output = output->wlr_output;
490 struct wlr_renderer *wlr_renderer =
491 wlr_backend_get_renderer(wlr_output->backend);
492
493 struct hikari_renderer renderer = {
494 .wlr_output = wlr_output, .wlr_renderer = wlr_renderer, .damage = damage
495 };
496
497 wlr_renderer_begin(wlr_renderer, wlr_output->width, wlr_output->height);
498
499 if (pixman_region32_not_empty(damage)) {
500 clear_output(&renderer);
501
502 hikari_server.mode->render(&renderer);
503 }
504
505 renderer_end(output, &renderer);
506 }
507
508 #ifdef HAVE_LAYERSHELL
509 static inline void
layer_for_each(struct wl_list * layers,void (* func)(struct wlr_surface *,int,int,void *),void * data)510 layer_for_each(struct wl_list *layers,
511 void (*func)(struct wlr_surface *, int, int, void *),
512 void *data)
513 {
514 struct hikari_layer *layer;
515 wl_list_for_each (layer, layers, layer_surfaces) {
516 wlr_layer_surface_v1_for_each_surface(layer->surface, func, data);
517 }
518 }
519 #endif
520
521 static void
send_frame_done(struct wlr_surface * surface,int sx,int sy,void * data)522 send_frame_done(struct wlr_surface *surface, int sx, int sy, void *data)
523 {
524 assert(surface != NULL);
525
526 struct timespec *now = data;
527 wlr_surface_send_frame_done(surface, now);
528 }
529
530 static inline void
frame_done(struct hikari_output * output)531 frame_done(struct hikari_output *output)
532 {
533 struct hikari_view *view;
534 struct timespec now;
535 clock_gettime(CLOCK_MONOTONIC, &now);
536
537 wl_list_for_each_reverse (view, &output->views, output_views) {
538 hikari_node_for_each_surface(
539 (struct hikari_node *)view, send_frame_done, &now);
540 }
541
542 #ifdef HAVE_XWAYLAND
543 struct hikari_xwayland_unmanaged_view *xwayland_unmanaged_view;
544 wl_list_for_each_reverse (xwayland_unmanaged_view,
545 &output->unmanaged_xwayland_views,
546 unmanaged_output_views) {
547 wlr_surface_for_each_surface(
548 xwayland_unmanaged_view->surface->surface, send_frame_done, &now);
549 }
550 #endif
551
552 #ifdef HAVE_LAYERSHELL
553 for (int i = 0; i < 4; i++) {
554 layer_for_each(&output->layers[i], send_frame_done, &now);
555 }
556 #endif
557 }
558
559 void
hikari_renderer_damage_frame_handler(struct wl_listener * listener,void * data)560 hikari_renderer_damage_frame_handler(struct wl_listener *listener, void *data)
561 {
562 struct hikari_output *output =
563 wl_container_of(listener, output, damage_frame);
564
565 pixman_region32_t buffer_damage;
566 pixman_region32_init(&buffer_damage);
567
568 bool needs_frame;
569 if (!wlr_output_damage_attach_render(
570 output->damage, &needs_frame, &buffer_damage)) {
571 goto render_done;
572 }
573
574 if (!needs_frame) {
575 wlr_output_rollback(output->wlr_output);
576 goto render_done;
577 }
578
579 render_output(output, &buffer_damage);
580
581 render_done:
582 pixman_region32_fini(&buffer_damage);
583
584 frame_done(output);
585 }
586
587 static inline void
render_public_views(struct hikari_renderer * renderer)588 render_public_views(struct hikari_renderer *renderer)
589 {
590 struct hikari_output *output = renderer->wlr_output->data;
591
592 struct hikari_view *view;
593 wl_list_for_each_reverse (view, &output->views, output_views) {
594 if (hikari_view_is_public(view) && !hikari_view_is_hidden(view)) {
595 renderer->geometry = hikari_view_border_geometry(view);
596
597 if (hikari_view_wants_border(view)) {
598 render_border(&view->border, renderer);
599 }
600
601 renderer->geometry = hikari_view_geometry(view);
602
603 hikari_node_for_each_surface(
604 (struct hikari_node *)view, render_surface, renderer);
605 }
606 }
607 }
608
609 static inline void
render_normal_mode_indication(struct hikari_renderer * renderer,struct hikari_view * focus_view)610 render_normal_mode_indication(
611 struct hikari_renderer *renderer, struct hikari_view *focus_view)
612 {
613 struct hikari_output *output = renderer->wlr_output->data;
614 struct hikari_group *group = focus_view->group;
615 struct hikari_view *first = hikari_group_first_view(group);
616 float *indicator_first = hikari_configuration->indicator_first;
617 float *indicator_grouped = hikari_configuration->indicator_grouped;
618
619 struct hikari_view *view;
620 wl_list_for_each_reverse (view, &group->visible_views, visible_group_views) {
621 if (view != focus_view && view->output == output) {
622 renderer->geometry = hikari_view_border_geometry(view);
623
624 if (first == view) {
625 render_indicator_frame(
626 &view->indicator_frame, indicator_first, renderer);
627 } else {
628 render_indicator_frame(
629 &view->indicator_frame, indicator_grouped, renderer);
630 }
631 }
632 }
633
634 if (focus_view->output == output) {
635 renderer->geometry = hikari_view_border_geometry(focus_view);
636
637 render_indicator_frame(&focus_view->indicator_frame,
638 hikari_configuration->indicator_selected,
639 renderer);
640
641 render_indicator(&hikari_server.indicator, renderer);
642 }
643 }
644
645 static inline void
render_cycling_workspace(struct hikari_renderer * renderer,struct hikari_view * focus_view)646 render_cycling_workspace(
647 struct hikari_renderer *renderer, struct hikari_view *focus_view)
648 {
649 struct hikari_output *output = renderer->wlr_output->data;
650
651 #ifdef HAVE_LAYERSHELL
652 render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], renderer);
653 render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], renderer);
654 #endif
655
656 struct hikari_view *view;
657 wl_list_for_each_reverse (view, &output->workspace->views, workspace_views) {
658 if (view != focus_view) {
659 render_view(renderer, view);
660 }
661 }
662
663 if (focus_view->output == output) {
664 render_view(renderer, focus_view);
665 }
666
667 #ifdef HAVE_LAYERSHELL
668 render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], renderer);
669 #endif
670
671 #ifdef HAVE_XWAYLAND
672 render_unmanaged_views(renderer);
673 #endif
674 }
675
676 void
hikari_renderer_normal_mode(struct hikari_renderer * renderer)677 hikari_renderer_normal_mode(struct hikari_renderer *renderer)
678 {
679 render_background(renderer, 1);
680
681 if (!hikari_server_is_indicating()) {
682 render_workspace(renderer);
683 } else {
684 struct hikari_view *focus_view = hikari_server.workspace->focus_view;
685
686 if (focus_view != NULL) {
687 if (hikari_server_is_cycling()) {
688 render_cycling_workspace(renderer, focus_view);
689 } else {
690 render_workspace(renderer);
691 }
692 render_normal_mode_indication(renderer, focus_view);
693 } else {
694 render_workspace(renderer);
695 }
696 }
697
698 #ifdef HAVE_LAYERSHELL
699 render_overlay(renderer);
700 #endif
701 }
702
703 void
hikari_renderer_group_assign_mode(struct hikari_renderer * renderer)704 hikari_renderer_group_assign_mode(struct hikari_renderer *renderer)
705 {
706 struct hikari_output *output = renderer->wlr_output->data;
707
708 render_background(renderer, 1);
709 render_workspace(renderer);
710
711 struct hikari_group_assign_mode *mode = &hikari_server.group_assign_mode;
712
713 assert(mode == (struct hikari_group_assign_mode *)hikari_server.mode);
714
715 struct hikari_group *group = mode->group;
716 struct hikari_view *focus_view = hikari_server.workspace->focus_view;
717
718 assert(focus_view != NULL);
719
720 if (group != NULL) {
721 struct hikari_view *first = hikari_group_first_view(group);
722 float *indicator_first = hikari_configuration->indicator_first;
723 float *indicator_grouped = hikari_configuration->indicator_grouped;
724
725 struct hikari_view *view;
726 wl_list_for_each_reverse (
727 view, &group->visible_views, visible_group_views) {
728 if (view->output == output && view != focus_view) {
729 renderer->geometry = hikari_view_border_geometry(view);
730
731 if (first == view) {
732 render_indicator_frame(
733 &view->indicator_frame, indicator_first, renderer);
734 } else {
735 render_indicator_frame(
736 &view->indicator_frame, indicator_grouped, renderer);
737 }
738 }
739 }
740 }
741
742 if (focus_view->output == output) {
743 renderer->geometry = hikari_view_border_geometry(focus_view);
744
745 render_indicator_frame(&focus_view->indicator_frame,
746 hikari_configuration->indicator_selected,
747 renderer);
748
749 render_indicator(&hikari_server.indicator, renderer);
750 }
751
752 #ifdef HAVE_LAYERSHELL
753 render_overlay(renderer);
754 #endif
755 }
756
757 void
hikari_renderer_input_grab_mode(struct hikari_renderer * renderer)758 hikari_renderer_input_grab_mode(struct hikari_renderer *renderer)
759 {
760 struct hikari_output *output = renderer->wlr_output->data;
761
762 render_background(renderer, 1);
763 render_workspace(renderer);
764
765 assert(hikari_server.workspace->focus_view != NULL);
766
767 struct hikari_view *view = hikari_server.workspace->focus_view;
768
769 if (view->output == output) {
770 renderer->geometry = hikari_view_border_geometry(view);
771 render_indicator_frame(&view->indicator_frame,
772 hikari_configuration->indicator_insert,
773 renderer);
774 }
775
776 #ifdef HAVE_LAYERSHELL
777 render_overlay(renderer);
778 #endif
779 }
780
781 static inline void
get_lock_indicator_geometry(struct hikari_output * output,struct wlr_box * geometry)782 get_lock_indicator_geometry(
783 struct hikari_output *output, struct wlr_box *geometry)
784 {
785 const int size = 100;
786
787 geometry->width = size;
788 geometry->height = size;
789
790 struct wlr_box output_geometry = { .x = 0,
791 .y = 0,
792 .width = output->geometry.width,
793 .height = output->geometry.height };
794
795 hikari_geometry_position_center(
796 geometry, &output_geometry, &geometry->x, &geometry->y);
797 }
798
799 static inline void
render_lock_indicator(struct hikari_renderer * renderer,struct hikari_lock_indicator * lock_indicator)800 render_lock_indicator(struct hikari_renderer *renderer,
801 struct hikari_lock_indicator *lock_indicator)
802 {
803 assert(lock_indicator != NULL);
804
805 struct wlr_texture *texture = lock_indicator->current;
806
807 if (texture == NULL) {
808 return;
809 }
810
811 float matrix[9];
812 struct wlr_renderer *wlr_renderer = renderer->wlr_renderer;
813 struct wlr_output *wlr_output = renderer->wlr_output;
814
815 struct wlr_box geometry;
816 get_lock_indicator_geometry(wlr_output->data, &geometry);
817 wlr_renderer_scissor(wlr_renderer, &geometry);
818 wlr_matrix_project_box(matrix, &geometry, 0, 0, wlr_output->transform_matrix);
819
820 wlr_render_texture_with_matrix(wlr_renderer, texture, matrix, 1);
821 }
822
823 void
hikari_renderer_lock_mode(struct hikari_renderer * renderer)824 hikari_renderer_lock_mode(struct hikari_renderer *renderer)
825 {
826 struct hikari_lock_mode *mode = &hikari_server.lock_mode;
827
828 assert(mode == (struct hikari_lock_mode *)hikari_server.mode);
829
830 render_background(renderer, 0.1);
831 render_public_views(renderer);
832 render_lock_indicator(renderer, mode->lock_indicator);
833 }
834
835 void
hikari_renderer_mark_assign_mode(struct hikari_renderer * renderer)836 hikari_renderer_mark_assign_mode(struct hikari_renderer *renderer)
837 {
838 struct hikari_output *output = renderer->wlr_output->data;
839
840 render_background(renderer, 1);
841 render_workspace(renderer);
842
843 struct hikari_mark_assign_mode *mode = &hikari_server.mark_assign_mode;
844
845 assert(mode == (struct hikari_mark_assign_mode *)hikari_server.mode);
846 assert(hikari_server.workspace->focus_view != NULL);
847
848 struct hikari_view *view = hikari_server.workspace->focus_view;
849
850 if (mode->pending_mark != NULL && mode->pending_mark->view != NULL &&
851 mode->pending_mark->view->output == output) {
852 renderer->geometry = hikari_view_border_geometry(mode->pending_mark->view);
853
854 render_indicator_frame(&mode->pending_mark->view->indicator_frame,
855 hikari_configuration->indicator_conflict,
856 renderer);
857 render_indicator(&mode->indicator, renderer);
858 }
859
860 if (view->output == output) {
861 renderer->geometry = hikari_view_border_geometry(view);
862
863 render_indicator_frame(&view->indicator_frame,
864 hikari_configuration->indicator_selected,
865 renderer);
866
867 render_indicator(&hikari_server.indicator, renderer);
868 }
869
870 #ifdef HAVE_LAYERSHELL
871 render_overlay(renderer);
872 #endif
873 }
874
875 void
hikari_renderer_move_mode(struct hikari_renderer * renderer)876 hikari_renderer_move_mode(struct hikari_renderer *renderer)
877 {
878 struct hikari_output *output = renderer->wlr_output->data;
879
880 render_background(renderer, 1);
881 render_workspace(renderer);
882
883 struct hikari_view *focus_view = hikari_server.workspace->focus_view;
884
885 if (focus_view->output == output && !hikari_view_is_hidden(focus_view)) {
886 renderer->geometry = hikari_view_border_geometry(focus_view);
887
888 render_indicator_frame(&focus_view->indicator_frame,
889 hikari_configuration->indicator_insert,
890 renderer);
891
892 render_indicator(&hikari_server.indicator, renderer);
893 }
894
895 #ifdef HAVE_LAYERSHELL
896 render_overlay(renderer);
897 #endif
898 }
899
900 void
hikari_renderer_resize_mode(struct hikari_renderer * renderer)901 hikari_renderer_resize_mode(struct hikari_renderer *renderer)
902 {
903 struct hikari_output *output = renderer->wlr_output->data;
904
905 render_background(renderer, 1);
906 render_workspace(renderer);
907
908 struct hikari_view *focus_view = hikari_server.workspace->focus_view;
909
910 if (focus_view->output == output) {
911 renderer->geometry = hikari_view_border_geometry(focus_view);
912
913 render_indicator_frame(&focus_view->indicator_frame,
914 hikari_configuration->indicator_insert,
915 renderer);
916
917 render_indicator(&hikari_server.indicator, renderer);
918 }
919
920 #ifdef HAVE_LAYERSHELL
921 render_overlay(renderer);
922 #endif
923 }
924
925 void
hikari_renderer_sheet_assign_mode(struct hikari_renderer * renderer)926 hikari_renderer_sheet_assign_mode(struct hikari_renderer *renderer)
927 {
928 struct hikari_output *output = renderer->wlr_output->data;
929
930 render_background(renderer, 1);
931 render_workspace(renderer);
932
933 assert(hikari_server.workspace->focus_view != NULL);
934 struct hikari_view *view = hikari_server.workspace->focus_view;
935
936 if (view->output == output) {
937 renderer->geometry = hikari_view_border_geometry(view);
938
939 render_indicator_frame(&view->indicator_frame,
940 hikari_configuration->indicator_selected,
941 renderer);
942
943 render_indicator(&hikari_server.indicator, renderer);
944 }
945
946 #ifdef HAVE_LAYERSHELL
947 render_overlay(renderer);
948 #endif
949 }
950
951 static inline void
render_default_workspace(struct hikari_renderer * renderer)952 render_default_workspace(struct hikari_renderer *renderer)
953 {
954 render_background(renderer, 1);
955 render_workspace(renderer);
956 #ifdef HAVE_LAYERSHELL
957 render_overlay(renderer);
958 #endif
959 }
960
961 void
hikari_renderer_dnd_mode(struct hikari_renderer * renderer)962 hikari_renderer_dnd_mode(struct hikari_renderer *renderer)
963 {
964 render_default_workspace(renderer);
965 }
966
967 void
hikari_renderer_layout_select_mode(struct hikari_renderer * renderer)968 hikari_renderer_layout_select_mode(struct hikari_renderer *renderer)
969 {
970 struct hikari_output *output = renderer->wlr_output->data;
971
972 render_background(renderer, 1);
973 render_workspace(renderer);
974
975 struct hikari_view *focus_view = hikari_server.workspace->focus_view;
976
977 if (focus_view != NULL && focus_view->output == output) {
978 renderer->geometry = hikari_view_border_geometry(focus_view);
979
980 render_indicator_frame(&focus_view->indicator_frame,
981 hikari_configuration->indicator_selected,
982 renderer);
983
984 render_indicator(&hikari_server.indicator, renderer);
985 }
986
987 #ifdef HAVE_LAYERSHELL
988 render_overlay(renderer);
989 #endif
990 }
991
992 void
hikari_renderer_mark_select_mode(struct hikari_renderer * renderer)993 hikari_renderer_mark_select_mode(struct hikari_renderer *renderer)
994 {
995 render_default_workspace(renderer);
996 }
997