diff options
Diffstat (limited to 'sway/output.c')
-rw-r--r-- | sway/output.c | 277 |
1 files changed, 0 insertions, 277 deletions
diff --git a/sway/output.c b/sway/output.c deleted file mode 100644 index c0f29c5a..00000000 --- a/sway/output.c +++ /dev/null | |||
@@ -1,277 +0,0 @@ | |||
1 | #include <strings.h> | ||
2 | #include <ctype.h> | ||
3 | #include <stdlib.h> | ||
4 | #include "sway/output.h" | ||
5 | #include "log.h" | ||
6 | #include "list.h" | ||
7 | |||
8 | void output_get_scaled_size(wlc_handle handle, struct wlc_size *size) { | ||
9 | *size = *wlc_output_get_resolution(handle); | ||
10 | uint32_t scale = wlc_output_get_scale(handle); | ||
11 | size->w /= scale; | ||
12 | size->h /= scale; | ||
13 | } | ||
14 | |||
15 | swayc_t *output_by_name(const char* name, const struct wlc_point *abs_pos) { | ||
16 | swayc_t *output = NULL; | ||
17 | // If there is no output directly next to the current one, use | ||
18 | // swayc_opposite_output to wrap. | ||
19 | if (strcasecmp(name, "left") == 0) { | ||
20 | output = swayc_adjacent_output(NULL, MOVE_LEFT, abs_pos, true); | ||
21 | if (!output) { | ||
22 | output = swayc_opposite_output(MOVE_RIGHT, abs_pos); | ||
23 | } | ||
24 | } else if (strcasecmp(name, "right") == 0) { | ||
25 | output = swayc_adjacent_output(NULL, MOVE_RIGHT, abs_pos, true); | ||
26 | if (!output) { | ||
27 | output = swayc_opposite_output(MOVE_LEFT, abs_pos); | ||
28 | } | ||
29 | } else if (strcasecmp(name, "up") == 0) { | ||
30 | output = swayc_adjacent_output(NULL, MOVE_UP, abs_pos, true); | ||
31 | if (!output) { | ||
32 | output = swayc_opposite_output(MOVE_DOWN, abs_pos); | ||
33 | } | ||
34 | } else if (strcasecmp(name, "down") == 0) { | ||
35 | output = swayc_adjacent_output(NULL, MOVE_DOWN, abs_pos, true); | ||
36 | if (!output) { | ||
37 | output = swayc_opposite_output(MOVE_UP, abs_pos); | ||
38 | } | ||
39 | } else { | ||
40 | for(int i = 0; i < root_container.children->length; ++i) { | ||
41 | swayc_t *c = root_container.children->items[i]; | ||
42 | if (c->type == C_OUTPUT && strcasecmp(c->name, name) == 0) { | ||
43 | return c; | ||
44 | } | ||
45 | } | ||
46 | } | ||
47 | return output; | ||
48 | } | ||
49 | |||
50 | swayc_t *swayc_opposite_output(enum movement_direction dir, | ||
51 | const struct wlc_point *abs_pos) { | ||
52 | |||
53 | // Search through all the outputs and pick the output whose edge covers the | ||
54 | // given position, and is at leftmost/rightmost/upmost/downmost side of the | ||
55 | // screen (decided by the direction given). | ||
56 | swayc_t *opposite = NULL; | ||
57 | char *dir_text = NULL; | ||
58 | switch(dir) { | ||
59 | case MOVE_LEFT: | ||
60 | case MOVE_RIGHT: ; | ||
61 | for (int i = 0; i < root_container.children->length; ++i) { | ||
62 | swayc_t *c = root_container.children->items[i]; | ||
63 | if (abs_pos->y >= c->y && abs_pos->y <= c->y + c->height) { | ||
64 | if (!opposite) { | ||
65 | opposite = c; | ||
66 | } else if ((dir == MOVE_LEFT && c->x < opposite->x) | ||
67 | || (dir == MOVE_RIGHT && c->x > opposite->x)) { | ||
68 | opposite = c; | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | dir_text = dir == MOVE_LEFT ? "leftmost" : "rightmost"; | ||
73 | break; | ||
74 | case MOVE_UP: | ||
75 | case MOVE_DOWN: ; | ||
76 | for (int i = 0; i < root_container.children->length; ++i) { | ||
77 | swayc_t *c = root_container.children->items[i]; | ||
78 | if (abs_pos->x >= c->x && abs_pos->x <= c->x + c->width) { | ||
79 | if (!opposite) { | ||
80 | opposite = c; | ||
81 | } else if ((dir == MOVE_UP && c->y < opposite->y) | ||
82 | || (dir == MOVE_DOWN && c->y > opposite->y)) { | ||
83 | opposite = c; | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | dir_text = dir == MOVE_UP ? "upmost" : "downmost"; | ||
88 | break; | ||
89 | default: | ||
90 | sway_abort("Function called with invalid argument."); | ||
91 | break; | ||
92 | } | ||
93 | if (opposite) { | ||
94 | sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s from y-position %i", | ||
95 | opposite->name, opposite->width, opposite->height, opposite->x, opposite->y, | ||
96 | dir_text, abs_pos->y); | ||
97 | } | ||
98 | return opposite; | ||
99 | } | ||
100 | |||
101 | // Position is where on the edge (as absolute position) the adjacent output should be searched for. | ||
102 | swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir, | ||
103 | const struct wlc_point *abs_pos, bool pick_closest) { | ||
104 | |||
105 | if (!output) { | ||
106 | output = swayc_active_output(); | ||
107 | } | ||
108 | // In order to find adjacent outputs we need to test that the outputs are | ||
109 | // aligned on one axis (decided by the direction given) and that the given | ||
110 | // position is within the edge of the adjacent output. If no such output | ||
111 | // exists we pick the adjacent output within the edge that is closest to | ||
112 | // the given position, if any. | ||
113 | swayc_t *adjacent = NULL; | ||
114 | char *dir_text = NULL; | ||
115 | switch(dir) { | ||
116 | case MOVE_LEFT: | ||
117 | case MOVE_RIGHT: ; | ||
118 | double delta_y = 0; | ||
119 | for(int i = 0; i < root_container.children->length; ++i) { | ||
120 | swayc_t *c = root_container.children->items[i]; | ||
121 | if (c == output || c->type != C_OUTPUT) { | ||
122 | continue; | ||
123 | } | ||
124 | bool x_aligned = dir == MOVE_LEFT ? | ||
125 | c->x + c->width == output->x : | ||
126 | c->x == output->x + output->width; | ||
127 | if (!x_aligned) { | ||
128 | continue; | ||
129 | } | ||
130 | if (abs_pos->y >= c->y && abs_pos->y <= c->y + c->height) { | ||
131 | delta_y = 0; | ||
132 | adjacent = c; | ||
133 | break; | ||
134 | } else if (pick_closest) { | ||
135 | // track closest adjacent output | ||
136 | double top_y = c->y, bottom_y = c->y + c->height; | ||
137 | if (top_y >= output->y && top_y <= output->y + output->height) { | ||
138 | double delta = top_y - abs_pos->y; | ||
139 | if (delta < 0) delta = -delta; | ||
140 | if (delta < delta_y || !adjacent) { | ||
141 | delta_y = delta; | ||
142 | adjacent = c; | ||
143 | } | ||
144 | } | ||
145 | // we check both points and pick the closest | ||
146 | if (bottom_y >= output->y && bottom_y <= output->y + output->height) { | ||
147 | double delta = bottom_y - abs_pos->y; | ||
148 | if (delta < 0) delta = -delta; | ||
149 | if (delta < delta_y || !adjacent) { | ||
150 | delta_y = delta; | ||
151 | adjacent = c; | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | dir_text = dir == MOVE_LEFT ? "left of" : "right of"; | ||
157 | if (adjacent && delta_y == 0) { | ||
158 | sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (y-position %i)", | ||
159 | adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y, | ||
160 | dir_text, output->name, abs_pos->y); | ||
161 | } else if (adjacent) { | ||
162 | // so we end up picking the closest adjacent output because | ||
163 | // there is no directly adjacent to the given position | ||
164 | sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (y-position %i, delta: %.0f)", | ||
165 | adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y, | ||
166 | dir_text, output->name, abs_pos->y, delta_y); | ||
167 | } | ||
168 | break; | ||
169 | case MOVE_UP: | ||
170 | case MOVE_DOWN: ; | ||
171 | double delta_x = 0; | ||
172 | for(int i = 0; i < root_container.children->length; ++i) { | ||
173 | swayc_t *c = root_container.children->items[i]; | ||
174 | if (c == output || c->type != C_OUTPUT) { | ||
175 | continue; | ||
176 | } | ||
177 | bool y_aligned = dir == MOVE_UP ? | ||
178 | c->y + c->height == output->y : | ||
179 | c->y == output->y + output->height; | ||
180 | if (!y_aligned) { | ||
181 | continue; | ||
182 | } | ||
183 | if (abs_pos->x >= c->x && abs_pos->x <= c->x + c->width) { | ||
184 | delta_x = 0; | ||
185 | adjacent = c; | ||
186 | break; | ||
187 | } else if (pick_closest) { | ||
188 | // track closest adjacent output | ||
189 | double left_x = c->x, right_x = c->x + c->width; | ||
190 | if (left_x >= output->x && left_x <= output->x + output->width) { | ||
191 | double delta = left_x - abs_pos->x; | ||
192 | if (delta < 0) delta = -delta; | ||
193 | if (delta < delta_x || !adjacent) { | ||
194 | delta_x = delta; | ||
195 | adjacent = c; | ||
196 | } | ||
197 | } | ||
198 | // we check both points and pick the closest | ||
199 | if (right_x >= output->x && right_x <= output->x + output->width) { | ||
200 | double delta = right_x - abs_pos->x; | ||
201 | if (delta < 0) delta = -delta; | ||
202 | if (delta < delta_x || !adjacent) { | ||
203 | delta_x = delta; | ||
204 | adjacent = c; | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | } | ||
209 | dir_text = dir == MOVE_UP ? "above" : "below"; | ||
210 | if (adjacent && delta_x == 0) { | ||
211 | sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (x-position %i)", | ||
212 | adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y, | ||
213 | dir_text, output->name, abs_pos->x); | ||
214 | } else if (adjacent) { | ||
215 | // so we end up picking the closest adjacent output because | ||
216 | // there is no directly adjacent to the given position | ||
217 | sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (x-position %i, delta: %.0f)", | ||
218 | adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y, | ||
219 | dir_text, output->name, abs_pos->x, delta_x); | ||
220 | } | ||
221 | break; | ||
222 | default: | ||
223 | sway_abort("Function called with invalid argument."); | ||
224 | break; | ||
225 | } | ||
226 | return adjacent; | ||
227 | } | ||
228 | |||
229 | void get_absolute_position(swayc_t *container, struct wlc_point *point) { | ||
230 | if (!container || !point) | ||
231 | sway_abort("Need container and wlc_point (was %p, %p).", container, point); | ||
232 | |||
233 | if (container->type == C_OUTPUT) { | ||
234 | // Coordinates are already absolute. | ||
235 | point->x = container->x; | ||
236 | point->y = container->y; | ||
237 | } else { | ||
238 | swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); | ||
239 | if (container->type == C_WORKSPACE) { | ||
240 | // Workspace coordinates are actually wrong/arbitrary, but should | ||
241 | // be same as output. | ||
242 | point->x = output->x; | ||
243 | point->y = output->y; | ||
244 | } else { | ||
245 | point->x = output->x + container->x; | ||
246 | point->y = output->y + container->y; | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | |||
251 | void get_absolute_center_position(swayc_t *container, struct wlc_point *point) { | ||
252 | get_absolute_position(container, point); | ||
253 | point->x += container->width/2; | ||
254 | point->y += container->height/2; | ||
255 | } | ||
256 | |||
257 | static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { | ||
258 | swayc_t *a = *(void **)_a; | ||
259 | swayc_t *b = *(void **)_b; | ||
260 | int retval = 0; | ||
261 | |||
262 | if (isdigit(a->name[0]) && isdigit(b->name[0])) { | ||
263 | int a_num = strtol(a->name, NULL, 10); | ||
264 | int b_num = strtol(b->name, NULL, 10); | ||
265 | retval = (a_num < b_num) ? -1 : (a_num > b_num); | ||
266 | } else if (isdigit(a->name[0])) { | ||
267 | retval = -1; | ||
268 | } else if (isdigit(b->name[0])) { | ||
269 | retval = 1; | ||
270 | } | ||
271 | |||
272 | return retval; | ||
273 | } | ||
274 | |||
275 | void sort_workspaces(swayc_t *output) { | ||
276 | list_stable_sort(output->children, sort_workspace_cmp_qsort); | ||
277 | } | ||