aboutsummaryrefslogtreecommitdiffstats
path: root/sway/output.c
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2017-11-11 11:00:18 -0500
committerLibravatar Drew DeVault <sir@cmpwn.com>2017-11-11 11:00:18 -0500
commit0ba6554c4f6c923274062862d895240eea4de350 (patch)
treee2b94dee4e8049f3a39365e82913559660f87bcd /sway/output.c
parentEstablish sway input submodule (diff)
downloadsway-0ba6554c4f6c923274062862d895240eea4de350.tar.gz
sway-0ba6554c4f6c923274062862d895240eea4de350.tar.zst
sway-0ba6554c4f6c923274062862d895240eea4de350.zip
Move sway's internal tree code to sway/tree/
Diffstat (limited to 'sway/output.c')
-rw-r--r--sway/output.c277
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
8void 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
15swayc_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
50swayc_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.
102swayc_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
229void 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
251void 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
257static 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
275void sort_workspaces(swayc_t *output) {
276 list_stable_sort(output->children, sort_workspace_cmp_qsort);
277}