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