1 #include <hikari/geometry.h>
2
3 #include <hikari/configuration.h>
4
5 #define SPLIT(n, x, y, width, height) \
6 void hikari_geometry_split_##n(struct wlr_box *src, \
7 int width, \
8 int gap, \
9 struct wlr_box *dst1, \
10 struct wlr_box *dst2) \
11 { \
12 int rest = src->width - gap - width; \
13 \
14 dst1->x = src->x; \
15 dst1->y = src->y; \
16 dst1->width = width; \
17 dst1->height = src->height; \
18 \
19 dst2->x = src->x + width + gap; \
20 dst2->y = src->y; \
21 dst2->width = rest; \
22 dst2->height = src->height; \
23 }
24
SPLIT(vertical,x,y,width,height)25 SPLIT(vertical, x, y, width, height)
26 SPLIT(horizontal, y, x, height, width)
27 #undef SPLIT
28
29 #define DYNAMIC_SCALE(name) \
30 int hikari_geometry_scale_dynamic_##name(struct wlr_box *src, \
31 struct wlr_box *geometry, \
32 double min_scale, \
33 double max_scale, \
34 int gap) \
35 { \
36 int min_##name = (src->name - gap) * min_scale; \
37 int max_##name = (src->name - gap) * max_scale; \
38 int name = geometry->name; \
39 \
40 if (name < min_##name) { \
41 return min_##name; \
42 } else if (name > max_##name) { \
43 return max_##name; \
44 } else { \
45 return name; \
46 } \
47 }
48
49 DYNAMIC_SCALE(width)
50 DYNAMIC_SCALE(height)
51 #undef DYNAMIC_SCALE
52
53 void
54 hikari_geometry_shrink(struct wlr_box *geometry, int gap)
55 {
56 geometry->x += gap;
57 geometry->y += gap;
58 geometry->width -= gap * 2;
59 geometry->height -= gap * 2;
60 }
61
62 void
hikari_geometry_constrain_absolute(struct wlr_box * geometry,struct wlr_box * usable_area,int x,int y)63 hikari_geometry_constrain_absolute(
64 struct wlr_box *geometry, struct wlr_box *usable_area, int x, int y)
65 {
66 int border = hikari_configuration->border;
67
68 int usable_max_x = usable_area->x + usable_area->width;
69 int usable_min_x = usable_area->x;
70 int usable_max_y = usable_area->y + usable_area->height;
71 int usable_min_y = usable_area->y;
72
73 if (x + geometry->width + border > usable_max_x) {
74 geometry->x = usable_max_x - geometry->width - border;
75 } else if (x - border < usable_min_x) {
76 geometry->x = usable_min_x + border;
77 } else {
78 geometry->x = x;
79 }
80
81 if (y + geometry->height + border > usable_max_y) {
82 geometry->y = usable_max_y - geometry->height - border;
83 } else if (y - border < usable_min_y) {
84 geometry->y = usable_min_y + border;
85 } else {
86 geometry->y = y;
87 }
88 }
89
90 void
hikari_geometry_constrain_relative(struct wlr_box * geometry,struct wlr_box * usable_area,int x,int y)91 hikari_geometry_constrain_relative(
92 struct wlr_box *geometry, struct wlr_box *usable_area, int x, int y)
93 {
94 int border = hikari_configuration->border;
95 int gap = hikari_configuration->gap * 2 - border;
96
97 int usable_max_x = usable_area->x + usable_area->width - gap;
98 int usable_min_x = usable_area->x - geometry->width + gap;
99 int usable_max_y = usable_area->y + usable_area->height - gap;
100 int usable_min_y = usable_area->y - geometry->height + gap;
101
102 if (x > usable_max_x) {
103 geometry->x = usable_max_x;
104 } else if (x < usable_min_x) {
105 geometry->x = usable_min_x;
106 } else {
107 geometry->x = x;
108 }
109
110 if (y > usable_max_y) {
111 geometry->y = usable_max_y;
112 } else if (y < usable_min_y) {
113 geometry->y = usable_min_y;
114 } else {
115 geometry->y = y;
116 }
117 }
118
119 #define CENTER(coord, dim) \
120 static int center_##coord( \
121 struct wlr_box *geometry, struct wlr_box *usable_area) \
122 { \
123 int center_usable_area_##coord = usable_area->dim / 2; \
124 int center_geometry_##coord = geometry->dim / 2; \
125 \
126 return usable_area->coord + center_usable_area_##coord - \
127 center_geometry_##coord; \
128 }
129
CENTER(x,width)130 CENTER(x, width)
131 CENTER(y, height)
132 #undef CENTER
133
134 static int
135 right_x(struct wlr_box *geometry, struct wlr_box *usable_area)
136 {
137 return usable_area->x + usable_area->width - geometry->width +
138 hikari_configuration->border;
139 }
140
141 static int
bottom_y(struct wlr_box * geometry,struct wlr_box * usable_area)142 bottom_y(struct wlr_box *geometry, struct wlr_box *usable_area)
143 {
144 return usable_area->y + usable_area->height - geometry->height +
145 hikari_configuration->border;
146 }
147
148 void
hikari_geometry_position_bottom_left(struct wlr_box * geometry,struct wlr_box * usable_area,int * x,int * y)149 hikari_geometry_position_bottom_left(
150 struct wlr_box *geometry, struct wlr_box *usable_area, int *x, int *y)
151 {
152 *x = usable_area->x;
153 *y = bottom_y(geometry, usable_area);
154 }
155
156 void
hikari_geometry_position_bottom_middle(struct wlr_box * geometry,struct wlr_box * usable_area,int * x,int * y)157 hikari_geometry_position_bottom_middle(
158 struct wlr_box *geometry, struct wlr_box *usable_area, int *x, int *y)
159 {
160 *x = center_x(geometry, usable_area);
161 *y = bottom_y(geometry, usable_area);
162 }
163
164 void
hikari_geometry_position_bottom_right(struct wlr_box * geometry,struct wlr_box * usable_area,int * x,int * y)165 hikari_geometry_position_bottom_right(
166 struct wlr_box *geometry, struct wlr_box *usable_area, int *x, int *y)
167 {
168 *x = right_x(geometry, usable_area);
169 *y = bottom_y(geometry, usable_area);
170 }
171
172 void
hikari_geometry_position_center(struct wlr_box * geometry,struct wlr_box * usable_area,int * x,int * y)173 hikari_geometry_position_center(
174 struct wlr_box *geometry, struct wlr_box *usable_area, int *x, int *y)
175 {
176 *x = center_x(geometry, usable_area);
177 *y = center_y(geometry, usable_area);
178 }
179
180 void
hikari_geometry_position_center_left(struct wlr_box * geometry,struct wlr_box * usable_area,int * x,int * y)181 hikari_geometry_position_center_left(
182 struct wlr_box *geometry, struct wlr_box *usable_area, int *x, int *y)
183 {
184 *x = usable_area->x;
185 *y = center_y(geometry, usable_area);
186 }
187
188 void
hikari_geometry_position_center_right(struct wlr_box * geometry,struct wlr_box * usable_area,int * x,int * y)189 hikari_geometry_position_center_right(
190 struct wlr_box *geometry, struct wlr_box *usable_area, int *x, int *y)
191 {
192 *x = right_x(geometry, usable_area);
193 *y = center_y(geometry, usable_area);
194 }
195
196 void
hikari_geometry_position_top_left(struct wlr_box * geometry,struct wlr_box * usable_area,int * x,int * y)197 hikari_geometry_position_top_left(
198 struct wlr_box *geometry, struct wlr_box *usable_area, int *x, int *y)
199 {
200 *x = usable_area->x;
201 *y = usable_area->y;
202 }
203
204 void
hikari_geometry_position_top_middle(struct wlr_box * geometry,struct wlr_box * usable_area,int * x,int * y)205 hikari_geometry_position_top_middle(
206 struct wlr_box *geometry, struct wlr_box *usable_area, int *x, int *y)
207 {
208 *x = center_x(geometry, usable_area);
209 *y = usable_area->y;
210 }
211
212 void
hikari_geometry_position_top_right(struct wlr_box * geometry,struct wlr_box * usable_area,int * x,int * y)213 hikari_geometry_position_top_right(
214 struct wlr_box *geometry, struct wlr_box *usable_area, int *x, int *y)
215 {
216 *x = right_x(geometry, usable_area);
217 *y = usable_area->y;
218 }
219
220 void
hikari_geometry_constrain_size(struct wlr_box * geometry,struct wlr_box * usable_area,struct wlr_box * constrained)221 hikari_geometry_constrain_size(struct wlr_box *geometry,
222 struct wlr_box *usable_area,
223 struct wlr_box *constrained)
224 {
225 if (geometry->x < 0) {
226 constrained->width = geometry->width + geometry->x;
227 constrained->x = 0;
228 } else {
229 int excess_width = geometry->width - (usable_area->width - geometry->x);
230
231 if (excess_width > 0) {
232 constrained->width = geometry->width - excess_width;
233 } else {
234 constrained->width = geometry->width;
235 }
236
237 constrained->x = geometry->x;
238 }
239
240 if (geometry->y < 0) {
241 constrained->height = geometry->height + geometry->y;
242 constrained->y = 0;
243 } else {
244 int excess_height = geometry->height - (usable_area->height - geometry->y);
245
246 if (excess_height > 0) {
247 constrained->height = geometry->height - excess_height;
248 } else {
249 constrained->height = geometry->height;
250 }
251
252 constrained->y = geometry->y;
253 }
254 }
255