aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/layout.c
diff options
context:
space:
mode:
authorLibravatar Tony Crisci <tony@dubstepdish.com>2018-03-29 23:41:33 -0400
committerLibravatar Tony Crisci <tony@dubstepdish.com>2018-03-29 23:41:33 -0400
commitdc8c9fbeb664518c76066cc28ee29452c6c30128 (patch)
tree88c2de0d08e00b2a30cb20cdfadfa6e53f5c59b4 /sway/tree/layout.c
parentMerge pull request #1653 from swaywm/revert-1647-refactor-tree (diff)
downloadsway-dc8c9fbeb664518c76066cc28ee29452c6c30128.tar.gz
sway-dc8c9fbeb664518c76066cc28ee29452c6c30128.tar.zst
sway-dc8c9fbeb664518c76066cc28ee29452c6c30128.zip
Revert "Merge pull request #1653 from swaywm/revert-1647-refactor-tree"
Diffstat (limited to 'sway/tree/layout.c')
-rw-r--r--sway/tree/layout.c133
1 files changed, 78 insertions, 55 deletions
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index de9e7b58..dc0ee5b4 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -6,24 +6,26 @@
6#include <string.h> 6#include <string.h>
7#include <wlr/types/wlr_output.h> 7#include <wlr/types/wlr_output.h>
8#include <wlr/types/wlr_output_layout.h> 8#include <wlr/types/wlr_output_layout.h>
9#include "sway/container.h" 9#include "sway/tree/container.h"
10#include "sway/layout.h" 10#include "sway/tree/layout.h"
11#include "sway/output.h" 11#include "sway/output.h"
12#include "sway/view.h" 12#include "sway/tree/view.h"
13#include "sway/input/seat.h" 13#include "sway/input/seat.h"
14#include "list.h" 14#include "list.h"
15#include "log.h" 15#include "log.h"
16 16
17swayc_t root_container; 17struct sway_container root_container;
18 18
19static void output_layout_change_notify(struct wl_listener *listener, void *data) { 19static void output_layout_change_notify(struct wl_listener *listener,
20 void *data) {
20 struct wlr_box *layout_box = wlr_output_layout_get_box( 21 struct wlr_box *layout_box = wlr_output_layout_get_box(
21 root_container.sway_root->output_layout, NULL); 22 root_container.sway_root->output_layout, NULL);
22 root_container.width = layout_box->width; 23 root_container.width = layout_box->width;
23 root_container.height = layout_box->height; 24 root_container.height = layout_box->height;
24 25
25 for (int i = 0 ; i < root_container.children->length; ++i) { 26 for (int i = 0 ; i < root_container.children->length; ++i) {
26 swayc_t *output_container = root_container.children->items[i]; 27 struct sway_container *output_container =
28 root_container.children->items[i];
27 if (output_container->type != C_OUTPUT) { 29 if (output_container->type != C_OUTPUT) {
28 continue; 30 continue;
29 } 31 }
@@ -43,7 +45,7 @@ static void output_layout_change_notify(struct wl_listener *listener, void *data
43 arrange_windows(&root_container, -1, -1); 45 arrange_windows(&root_container, -1, -1);
44} 46}
45 47
46void init_layout(void) { 48void layout_init(void) {
47 root_container.id = 0; // normally assigned in new_swayc() 49 root_container.id = 0; // normally assigned in new_swayc()
48 root_container.type = C_ROOT; 50 root_container.type = C_ROOT;
49 root_container.layout = L_NONE; 51 root_container.layout = L_NONE;
@@ -62,9 +64,9 @@ void init_layout(void) {
62 &root_container.sway_root->output_layout_change); 64 &root_container.sway_root->output_layout_change);
63} 65}
64 66
65static int index_child(const swayc_t *child) { 67static int index_child(const struct sway_container *child) {
66 // TODO handle floating 68 // TODO handle floating
67 swayc_t *parent = child->parent; 69 struct sway_container *parent = child->parent;
68 int i, len; 70 int i, len;
69 len = parent->children->length; 71 len = parent->children->length;
70 for (i = 0; i < len; ++i) { 72 for (i = 0; i < len; ++i) {
@@ -79,16 +81,18 @@ static int index_child(const swayc_t *child) {
79 return i; 81 return i;
80} 82}
81 83
82swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) { 84struct sway_container *container_add_sibling(struct sway_container *fixed,
85 struct sway_container *active) {
83 // TODO handle floating 86 // TODO handle floating
84 swayc_t *parent = fixed->parent; 87 struct sway_container *parent = fixed->parent;
85 int i = index_child(fixed); 88 int i = index_child(fixed);
86 list_insert(parent->children, i + 1, active); 89 list_insert(parent->children, i + 1, active);
87 active->parent = parent; 90 active->parent = parent;
88 return active->parent; 91 return active->parent;
89} 92}
90 93
91void add_child(swayc_t *parent, swayc_t *child) { 94void container_add_child(struct sway_container *parent,
95 struct sway_container *child) {
92 wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", 96 wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)",
93 child, child->type, child->width, child->height, 97 child, child->type, child->width, child->height,
94 parent, parent->type, parent->width, parent->height); 98 parent, parent->type, parent->width, parent->height);
@@ -96,15 +100,17 @@ void add_child(swayc_t *parent, swayc_t *child) {
96 child->parent = parent; 100 child->parent = parent;
97 // set focus for this container 101 // set focus for this container
98 /* TODO WLR 102 /* TODO WLR
99 if (parent->type == C_WORKSPACE && child->type == C_VIEW && (parent->workspace_layout == L_TABBED || parent->workspace_layout == L_STACKED)) { 103 if (parent->type == C_WORKSPACE && child->type == C_VIEW &&
104 (parent->workspace_layout == L_TABBED || parent->workspace_layout ==
105 L_STACKED)) {
100 child = new_container(child, parent->workspace_layout); 106 child = new_container(child, parent->workspace_layout);
101 } 107 }
102 */ 108 */
103} 109}
104 110
105swayc_t *remove_child(swayc_t *child) { 111struct sway_container *container_remove_child(struct sway_container *child) {
106 int i; 112 int i;
107 swayc_t *parent = child->parent; 113 struct sway_container *parent = child->parent;
108 for (i = 0; i < parent->children->length; ++i) { 114 for (i = 0; i < parent->children->length; ++i) {
109 if (parent->children->items[i] == child) { 115 if (parent->children->items[i] == child) {
110 list_del(parent->children, i); 116 list_del(parent->children, i);
@@ -115,7 +121,8 @@ swayc_t *remove_child(swayc_t *child) {
115 return parent; 121 return parent;
116} 122}
117 123
118enum swayc_layouts default_layout(swayc_t *output) { 124enum sway_container_layout container_get_default_layout(
125 struct sway_container *output) {
119 /* TODO WLR 126 /* TODO WLR
120 if (config->default_layout != L_NONE) { 127 if (config->default_layout != L_NONE) {
121 //return config->default_layout; 128 //return config->default_layout;
@@ -129,8 +136,8 @@ enum swayc_layouts default_layout(swayc_t *output) {
129} 136}
130 137
131static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { 138static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
132 swayc_t *a = *(void **)_a; 139 struct sway_container *a = *(void **)_a;
133 swayc_t *b = *(void **)_b; 140 struct sway_container *b = *(void **)_b;
134 int retval = 0; 141 int retval = 0;
135 142
136 if (isdigit(a->name[0]) && isdigit(b->name[0])) { 143 if (isdigit(a->name[0]) && isdigit(b->name[0])) {
@@ -146,21 +153,22 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
146 return retval; 153 return retval;
147} 154}
148 155
149void sort_workspaces(swayc_t *output) { 156void container_sort_workspaces(struct sway_container *output) {
150 list_stable_sort(output->children, sort_workspace_cmp_qsort); 157 list_stable_sort(output->children, sort_workspace_cmp_qsort);
151} 158}
152 159
153static void apply_horiz_layout(swayc_t *container, const double x, 160static void apply_horiz_layout(struct sway_container *container, const double x,
154 const double y, const double width, 161 const double y, const double width,
155 const double height, const int start, 162 const double height, const int start,
156 const int end); 163 const int end);
157 164
158static void apply_vert_layout(swayc_t *container, const double x, 165static void apply_vert_layout(struct sway_container *container, const double x,
159 const double y, const double width, 166 const double y, const double width,
160 const double height, const int start, 167 const double height, const int start,
161 const int end); 168 const int end);
162 169
163void arrange_windows(swayc_t *container, double width, double height) { 170void arrange_windows(struct sway_container *container,
171 double width, double height) {
164 int i; 172 int i;
165 if (width == -1 || height == -1) { 173 if (width == -1 || height == -1) {
166 width = container->width; 174 width = container->width;
@@ -181,7 +189,7 @@ void arrange_windows(swayc_t *container, double width, double height) {
181 case C_ROOT: 189 case C_ROOT:
182 // TODO: wlr_output_layout probably 190 // TODO: wlr_output_layout probably
183 for (i = 0; i < container->children->length; ++i) { 191 for (i = 0; i < container->children->length; ++i) {
184 swayc_t *output = container->children->items[i]; 192 struct sway_container *output = container->children->items[i];
185 wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", 193 wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f",
186 output->name, output->x, output->y); 194 output->name, output->x, output->y);
187 arrange_windows(output, -1, -1); 195 arrange_windows(output, -1, -1);
@@ -197,13 +205,14 @@ void arrange_windows(swayc_t *container, double width, double height) {
197 } 205 }
198 // arrange all workspaces: 206 // arrange all workspaces:
199 for (i = 0; i < container->children->length; ++i) { 207 for (i = 0; i < container->children->length; ++i) {
200 swayc_t *child = container->children->items[i]; 208 struct sway_container *child = container->children->items[i];
201 arrange_windows(child, -1, -1); 209 arrange_windows(child, -1, -1);
202 } 210 }
203 return; 211 return;
204 case C_WORKSPACE: 212 case C_WORKSPACE:
205 { 213 {
206 swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); 214 struct sway_container *output =
215 container_parent(container, C_OUTPUT);
207 struct wlr_box *area = &output->sway_output->usable_area; 216 struct wlr_box *area = &output->sway_output->usable_area;
208 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", 217 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
209 area->width, area->height, area->x, area->y); 218 area->width, area->height, area->x, area->y);
@@ -252,14 +261,15 @@ void arrange_windows(swayc_t *container, double width, double height) {
252 } 261 }
253} 262}
254 263
255static void apply_horiz_layout(swayc_t *container, 264static void apply_horiz_layout(struct sway_container *container,
256 const double x, const double y, 265 const double x, const double y,
257 const double width, const double height, 266 const double width, const double height,
258 const int start, const int end) { 267 const int start, const int end) {
259 double scale = 0; 268 double scale = 0;
260 // Calculate total width 269 // Calculate total width
261 for (int i = start; i < end; ++i) { 270 for (int i = start; i < end; ++i) {
262 double *old_width = &((swayc_t *)container->children->items[i])->width; 271 double *old_width =
272 &((struct sway_container *)container->children->items[i])->width;
263 if (*old_width <= 0) { 273 if (*old_width <= 0) {
264 if (end - start > 1) { 274 if (end - start > 1) {
265 *old_width = width / (end - start - 1); 275 *old_width = width / (end - start - 1);
@@ -276,7 +286,7 @@ static void apply_horiz_layout(swayc_t *container,
276 if (scale > 0.1) { 286 if (scale > 0.1) {
277 wlr_log(L_DEBUG, "Arranging %p horizontally", container); 287 wlr_log(L_DEBUG, "Arranging %p horizontally", container);
278 for (int i = start; i < end; ++i) { 288 for (int i = start; i < end; ++i) {
279 swayc_t *child = container->children->items[i]; 289 struct sway_container *child = container->children->items[i];
280 wlr_log(L_DEBUG, 290 wlr_log(L_DEBUG,
281 "Calculating arrangement for %p:%d (will scale %f by %f)", 291 "Calculating arrangement for %p:%d (will scale %f by %f)",
282 child, child->type, width, scale); 292 child, child->type, width, scale);
@@ -301,7 +311,7 @@ static void apply_horiz_layout(swayc_t *container,
301 } 311 }
302} 312}
303 313
304void apply_vert_layout(swayc_t *container, 314void apply_vert_layout(struct sway_container *container,
305 const double x, const double y, 315 const double x, const double y,
306 const double width, const double height, const int start, 316 const double width, const double height, const int start,
307 const int end) { 317 const int end) {
@@ -309,7 +319,8 @@ void apply_vert_layout(swayc_t *container,
309 double scale = 0; 319 double scale = 0;
310 // Calculate total height 320 // Calculate total height
311 for (i = start; i < end; ++i) { 321 for (i = start; i < end; ++i) {
312 double *old_height = &((swayc_t *)container->children->items[i])->height; 322 double *old_height =
323 &((struct sway_container *)container->children->items[i])->height;
313 if (*old_height <= 0) { 324 if (*old_height <= 0) {
314 if (end - start > 1) { 325 if (end - start > 1) {
315 *old_height = height / (end - start - 1); 326 *old_height = height / (end - start - 1);
@@ -326,7 +337,7 @@ void apply_vert_layout(swayc_t *container,
326 if (scale > 0.1) { 337 if (scale > 0.1) {
327 wlr_log(L_DEBUG, "Arranging %p vertically", container); 338 wlr_log(L_DEBUG, "Arranging %p vertically", container);
328 for (i = start; i < end; ++i) { 339 for (i = start; i < end; ++i) {
329 swayc_t *child = container->children->items[i]; 340 struct sway_container *child = container->children->items[i];
330 wlr_log(L_DEBUG, 341 wlr_log(L_DEBUG,
331 "Calculating arrangement for %p:%d (will scale %f by %f)", 342 "Calculating arrangement for %p:%d (will scale %f by %f)",
332 child, child->type, height, scale); 343 child, child->type, height, scale);
@@ -354,15 +365,16 @@ void apply_vert_layout(swayc_t *container,
354/** 365/**
355 * Get swayc in the direction of newly entered output. 366 * Get swayc in the direction of newly entered output.
356 */ 367 */
357static swayc_t *get_swayc_in_output_direction(swayc_t *output, 368static struct sway_container *get_swayc_in_output_direction(
358 enum movement_direction dir, struct sway_seat *seat) { 369 struct sway_container *output, enum movement_direction dir,
370 struct sway_seat *seat) {
359 if (!output) { 371 if (!output) {
360 return NULL; 372 return NULL;
361 } 373 }
362 374
363 swayc_t *ws = sway_seat_get_focus_inactive(seat, output); 375 struct sway_container *ws = sway_seat_get_focus_inactive(seat, output);
364 if (ws->type != C_WORKSPACE) { 376 if (ws->type != C_WORKSPACE) {
365 ws = swayc_parent_by_type(ws, C_WORKSPACE); 377 ws = container_parent(ws, C_WORKSPACE);
366 } 378 }
367 379
368 if (ws == NULL) { 380 if (ws == NULL) {
@@ -380,13 +392,15 @@ static swayc_t *get_swayc_in_output_direction(swayc_t *output,
380 return ws->children->items[0]; 392 return ws->children->items[0];
381 case MOVE_UP: 393 case MOVE_UP:
382 case MOVE_DOWN: { 394 case MOVE_DOWN: {
383 swayc_t *focused = sway_seat_get_focus_inactive(seat, ws); 395 struct sway_container *focused =
396 sway_seat_get_focus_inactive(seat, ws);
384 if (focused && focused->parent) { 397 if (focused && focused->parent) {
385 swayc_t *parent = focused->parent; 398 struct sway_container *parent = focused->parent;
386 if (parent->layout == L_VERT) { 399 if (parent->layout == L_VERT) {
387 if (dir == MOVE_UP) { 400 if (dir == MOVE_UP) {
388 // get child furthest down on new output 401 // get child furthest down on new output
389 return parent->children->items[parent->children->length-1]; 402 int idx = parent->children->length - 1;
403 return parent->children->items[idx];
390 } else if (dir == MOVE_DOWN) { 404 } else if (dir == MOVE_DOWN) {
391 // get child furthest up on new output 405 // get child furthest up on new output
392 return parent->children->items[0]; 406 return parent->children->items[0];
@@ -404,13 +418,14 @@ static swayc_t *get_swayc_in_output_direction(swayc_t *output,
404 return ws; 418 return ws;
405} 419}
406 420
407static void get_layout_center_position(swayc_t *container, int *x, int *y) { 421static void get_layout_center_position(struct sway_container *container,
422 int *x, int *y) {
408 // FIXME view coords are inconsistently referred to in layout/output systems 423 // FIXME view coords are inconsistently referred to in layout/output systems
409 if (container->type == C_OUTPUT) { 424 if (container->type == C_OUTPUT) {
410 *x = container->x + container->width/2; 425 *x = container->x + container->width/2;
411 *y = container->y + container->height/2; 426 *y = container->y + container->height/2;
412 } else { 427 } else {
413 swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); 428 struct sway_container *output = container_parent(container, C_OUTPUT);
414 if (container->type == C_WORKSPACE) { 429 if (container->type == C_WORKSPACE) {
415 // Workspace coordinates are actually wrong/arbitrary, but should 430 // Workspace coordinates are actually wrong/arbitrary, but should
416 // be same as output. 431 // be same as output.
@@ -423,7 +438,8 @@ static void get_layout_center_position(swayc_t *container, int *x, int *y) {
423 } 438 }
424} 439}
425 440
426static bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out) { 441static bool sway_dir_to_wlr(enum movement_direction dir,
442 enum wlr_direction *out) {
427 switch (dir) { 443 switch (dir) {
428 case MOVE_UP: 444 case MOVE_UP:
429 *out = WLR_DIRECTION_UP; 445 *out = WLR_DIRECTION_UP;
@@ -444,12 +460,12 @@ static bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out
444 return true; 460 return true;
445} 461}
446 462
447static swayc_t *sway_output_from_wlr(struct wlr_output *output) { 463static struct sway_container *sway_output_from_wlr(struct wlr_output *output) {
448 if (output == NULL) { 464 if (output == NULL) {
449 return NULL; 465 return NULL;
450 } 466 }
451 for (int i = 0; i < root_container.children->length; ++i) { 467 for (int i = 0; i < root_container.children->length; ++i) {
452 swayc_t *o = root_container.children->items[i]; 468 struct sway_container *o = root_container.children->items[i];
453 if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) { 469 if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) {
454 return o; 470 return o;
455 } 471 }
@@ -457,13 +473,14 @@ static swayc_t *sway_output_from_wlr(struct wlr_output *output) {
457 return NULL; 473 return NULL;
458} 474}
459 475
460static swayc_t *get_swayc_in_direction_under(swayc_t *container, 476static struct sway_container *get_swayc_in_direction_under(
461 enum movement_direction dir, struct sway_seat *seat, swayc_t *limit) { 477 struct sway_container *container, enum movement_direction dir,
478 struct sway_seat *seat, struct sway_container *limit) {
462 if (dir == MOVE_CHILD) { 479 if (dir == MOVE_CHILD) {
463 return sway_seat_get_focus_inactive(seat, container); 480 return sway_seat_get_focus_inactive(seat, container);
464 } 481 }
465 482
466 swayc_t *parent = container->parent; 483 struct sway_container *parent = container->parent;
467 if (dir == MOVE_PARENT) { 484 if (dir == MOVE_PARENT) {
468 if (parent->type == C_OUTPUT) { 485 if (parent->type == C_OUTPUT) {
469 return NULL; 486 return NULL;
@@ -496,9 +513,10 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container,
496 /* 513 /*
497 if (container->type == C_VIEW && swayc_is_fullscreen(container)) { 514 if (container->type == C_VIEW && swayc_is_fullscreen(container)) {
498 wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); 515 wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output");
499 container = swayc_parent_by_type(container, C_OUTPUT); 516 container = container_parent(container, C_OUTPUT);
500 get_layout_center_position(container, &abs_pos); 517 get_layout_center_position(container, &abs_pos);
501 swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); 518 struct sway_container *output =
519 swayc_adjacent_output(container, dir, &abs_pos, true);
502 return get_swayc_in_output_direction(output, dir); 520 return get_swayc_in_output_direction(output, dir);
503 } 521 }
504 if (container->type == C_WORKSPACE && container->fullscreen) { 522 if (container->type == C_WORKSPACE && container->fullscreen) {
@@ -507,7 +525,7 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container,
507 } 525 }
508 */ 526 */
509 527
510 swayc_t *wrap_candidate = NULL; 528 struct sway_container *wrap_candidate = NULL;
511 while (true) { 529 while (true) {
512 // Test if we can even make a difference here 530 // Test if we can even make a difference here
513 bool can_move = false; 531 bool can_move = false;
@@ -521,16 +539,19 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container,
521 } 539 }
522 int lx, ly; 540 int lx, ly;
523 get_layout_center_position(container, &lx, &ly); 541 get_layout_center_position(container, &lx, &ly);
524 struct wlr_output_layout *layout = root_container.sway_root->output_layout; 542 struct wlr_output_layout *layout =
543 root_container.sway_root->output_layout;
525 struct wlr_output *wlr_adjacent = 544 struct wlr_output *wlr_adjacent =
526 wlr_output_layout_adjacent_output(layout, wlr_dir, 545 wlr_output_layout_adjacent_output(layout, wlr_dir,
527 container->sway_output->wlr_output, lx, ly); 546 container->sway_output->wlr_output, lx, ly);
528 swayc_t *adjacent = sway_output_from_wlr(wlr_adjacent); 547 struct sway_container *adjacent =
548 sway_output_from_wlr(wlr_adjacent);
529 549
530 if (!adjacent || adjacent == container) { 550 if (!adjacent || adjacent == container) {
531 return wrap_candidate; 551 return wrap_candidate;
532 } 552 }
533 swayc_t *next = get_swayc_in_output_direction(adjacent, dir, seat); 553 struct sway_container *next =
554 get_swayc_in_output_direction(adjacent, dir, seat);
534 if (next == NULL) { 555 if (next == NULL) {
535 return NULL; 556 return NULL;
536 } 557 }
@@ -570,8 +591,9 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container,
570 } 591 }
571 } 592 }
572 } else { 593 } else {
573 wlr_log(L_DEBUG, "%s cont %d-%p dir %i sibling %d: %p", __func__, 594 wlr_log(L_DEBUG,
574 idx, container, dir, desired, parent->children->items[desired]); 595 "cont %d-%p dir %i sibling %d: %p", idx,
596 container, dir, desired, parent->children->items[desired]);
575 return parent->children->items[desired]; 597 return parent->children->items[desired];
576 } 598 }
577 } 599 }
@@ -587,7 +609,8 @@ static swayc_t *get_swayc_in_direction_under(swayc_t *container,
587 } 609 }
588} 610}
589 611
590swayc_t *get_swayc_in_direction(swayc_t *container, struct sway_seat *seat, 612struct sway_container *container_get_in_direction(
613 struct sway_container *container, struct sway_seat *seat,
591 enum movement_direction dir) { 614 enum movement_direction dir) {
592 return get_swayc_in_direction_under(container, dir, seat, NULL); 615 return get_swayc_in_direction_under(container, dir, seat, NULL);
593} 616}