diff options
-rw-r--r-- | include/sway/input/seat.h | 2 | ||||
-rw-r--r-- | include/sway/tree/container.h | 2 | ||||
-rw-r--r-- | include/sway/tree/layout.h | 3 | ||||
-rw-r--r-- | sway/commands.c | 4 | ||||
-rw-r--r-- | sway/commands/kill.c | 29 | ||||
-rw-r--r-- | sway/commands/split.c | 107 | ||||
-rw-r--r-- | sway/input/seat.c | 32 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/tree/container.c | 7 | ||||
-rw-r--r-- | sway/tree/layout.c | 99 |
10 files changed, 240 insertions, 46 deletions
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 31210a5a..38795e14 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -74,7 +74,7 @@ struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, | |||
74 | struct sway_container *container); | 74 | struct sway_container *container); |
75 | 75 | ||
76 | struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, | 76 | struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, |
77 | enum sway_container_type type); | 77 | struct sway_container *container, enum sway_container_type type); |
78 | 78 | ||
79 | void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); | 79 | void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); |
80 | 80 | ||
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 6aa66da0..46f1c5ab 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -87,6 +87,8 @@ struct sway_container { | |||
87 | } events; | 87 | } events; |
88 | }; | 88 | }; |
89 | 89 | ||
90 | struct sway_container *container_create(enum sway_container_type type); | ||
91 | |||
90 | // TODO only one container create function and pass the type? | 92 | // TODO only one container create function and pass the type? |
91 | struct sway_container *container_output_create( | 93 | struct sway_container *container_output_create( |
92 | struct sway_output *sway_output); | 94 | struct sway_output *sway_output); |
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 0a904c4b..79c14eda 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h | |||
@@ -54,4 +54,7 @@ void arrange_windows(struct sway_container *container, | |||
54 | struct sway_container *container_get_in_direction(struct sway_container | 54 | struct sway_container *container_get_in_direction(struct sway_container |
55 | *container, struct sway_seat *seat, enum movement_direction dir); | 55 | *container, struct sway_seat *seat, enum movement_direction dir); |
56 | 56 | ||
57 | struct sway_container *container_split(struct sway_container *child, | ||
58 | enum sway_container_layout layout); | ||
59 | |||
57 | #endif | 60 | #endif |
diff --git a/sway/commands.c b/sway/commands.c index 90544220..c85ddf7a 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -163,6 +163,10 @@ static struct cmd_handler command_handlers[] = { | |||
163 | { "kill", cmd_kill }, | 163 | { "kill", cmd_kill }, |
164 | { "layout", cmd_layout }, | 164 | { "layout", cmd_layout }, |
165 | { "reload", cmd_reload }, | 165 | { "reload", cmd_reload }, |
166 | { "split", cmd_split }, | ||
167 | { "splith", cmd_splith }, | ||
168 | { "splitt", cmd_splitt }, | ||
169 | { "splitv", cmd_splitv }, | ||
166 | }; | 170 | }; |
167 | 171 | ||
168 | static int handler_compare(const void *_a, const void *_b) { | 172 | static int handler_compare(const void *_a, const void *_b) { |
diff --git a/sway/commands/kill.c b/sway/commands/kill.c index f6774767..80120832 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c | |||
@@ -3,21 +3,30 @@ | |||
3 | #include "sway/input/input-manager.h" | 3 | #include "sway/input/input-manager.h" |
4 | #include "sway/input/seat.h" | 4 | #include "sway/input/seat.h" |
5 | #include "sway/tree/view.h" | 5 | #include "sway/tree/view.h" |
6 | #include "sway/tree/container.h" | ||
6 | #include "sway/commands.h" | 7 | #include "sway/commands.h" |
7 | 8 | ||
8 | struct cmd_results *cmd_kill(int argc, char **argv) { | 9 | struct cmd_results *cmd_kill(int argc, char **argv) { |
9 | enum sway_container_type type = config->handler_context.current_container->type; | 10 | struct sway_container *con = |
10 | if (type != C_VIEW && type != C_CONTAINER) { | 11 | config->handler_context.current_container; |
12 | |||
13 | switch (con->type) { | ||
14 | case C_ROOT: | ||
15 | case C_OUTPUT: | ||
16 | case C_WORKSPACE: | ||
11 | return cmd_results_new(CMD_INVALID, NULL, | 17 | return cmd_results_new(CMD_INVALID, NULL, |
12 | "Can only kill views and containers with this command"); | 18 | "Can only kill views and containers with this command"); |
13 | } | 19 | break; |
14 | 20 | case C_CONTAINER: | |
15 | // TODO close arbitrary containers without a view | 21 | con = container_destroy(con); |
16 | struct sway_view *view = | 22 | con = container_reap_empty(con); |
17 | config->handler_context.current_container->sway_view; | 23 | arrange_windows(con, -1, -1); |
18 | 24 | break; | |
19 | if (view) { | 25 | case C_VIEW: |
20 | view_close(view); | 26 | view_close(con->sway_view); |
27 | break; | ||
28 | default: | ||
29 | break; | ||
21 | } | 30 | } |
22 | 31 | ||
23 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 32 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/split.c b/sway/commands/split.c new file mode 100644 index 00000000..6df20e88 --- /dev/null +++ b/sway/commands/split.c | |||
@@ -0,0 +1,107 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/tree/container.h" | ||
5 | #include "sway/tree/layout.h" | ||
6 | #include "sway/tree/view.h" | ||
7 | #include "sway/input/input-manager.h" | ||
8 | #include "sway/input/seat.h" | ||
9 | #include "log.h" | ||
10 | |||
11 | static struct cmd_results *_do_split(int argc, char **argv, int layout) { | ||
12 | char *name = layout == L_VERT ? "splitv" : | ||
13 | layout == L_HORIZ ? "splith" : "split"; | ||
14 | struct cmd_results *error = NULL; | ||
15 | if (config->reading) { | ||
16 | return cmd_results_new(CMD_FAILURE, name, | ||
17 | "Can't be used in config file."); | ||
18 | } | ||
19 | if (!config->active) { | ||
20 | return cmd_results_new(CMD_FAILURE, name, | ||
21 | "Can only be used when sway is running."); | ||
22 | } | ||
23 | if ((error = checkarg(argc, name, EXPECTED_EQUAL_TO, 0))) { | ||
24 | return error; | ||
25 | } | ||
26 | |||
27 | struct sway_container *focused = config->handler_context.current_container; | ||
28 | |||
29 | // TODO floating: dont split | ||
30 | |||
31 | /* Case that focus is on an workspace with 0/1 children.change its layout */ | ||
32 | if (focused->type == C_WORKSPACE && focused->children->length <= 1) { | ||
33 | wlr_log(L_DEBUG, "changing workspace layout"); | ||
34 | container_set_layout(focused, layout); | ||
35 | } else if (focused->type != C_WORKSPACE && | ||
36 | focused->parent->children->length == 1) { | ||
37 | /* Case of no siblings. change parent layout */ | ||
38 | wlr_log(L_DEBUG, "changing container layout"); | ||
39 | container_set_layout(focused->parent, layout); | ||
40 | } else { | ||
41 | // regular case where new split container is build around focused | ||
42 | // container or in case of workspace, container inherits its children | ||
43 | wlr_log(L_DEBUG, | ||
44 | "Adding new container around current focused container"); | ||
45 | wlr_log(L_INFO, "FOCUSED SIZE: %.f %.f", | ||
46 | focused->width, focused->height); | ||
47 | |||
48 | struct sway_container *parent = container_split(focused, layout); | ||
49 | arrange_windows(parent, -1, -1); | ||
50 | } | ||
51 | |||
52 | // TODO borders: update borders | ||
53 | |||
54 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
55 | } | ||
56 | |||
57 | struct cmd_results *cmd_split(int argc, char **argv) { | ||
58 | struct cmd_results *error = NULL; | ||
59 | if (config->reading) { | ||
60 | return cmd_results_new(CMD_FAILURE, "split", | ||
61 | "Can't be used in config file."); | ||
62 | } | ||
63 | if (!config->active) { | ||
64 | return cmd_results_new(CMD_FAILURE, "split", | ||
65 | "Can only be used when sway is running."); | ||
66 | } | ||
67 | if ((error = checkarg(argc, "split", EXPECTED_EQUAL_TO, 1))) { | ||
68 | return error; | ||
69 | } | ||
70 | if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { | ||
71 | _do_split(argc - 1, argv + 1, L_VERT); | ||
72 | } else if (strcasecmp(argv[0], "h") == 0 || | ||
73 | strcasecmp(argv[0], "horizontal") == 0) { | ||
74 | _do_split(argc - 1, argv + 1, L_HORIZ); | ||
75 | } else if (strcasecmp(argv[0], "t") == 0 || | ||
76 | strcasecmp(argv[0], "toggle") == 0) { | ||
77 | struct sway_container *focused = | ||
78 | config->handler_context.current_container; | ||
79 | if (focused->parent->layout == L_VERT) { | ||
80 | _do_split(argc - 1, argv + 1, L_HORIZ); | ||
81 | } else { | ||
82 | _do_split(argc - 1, argv + 1, L_VERT); | ||
83 | } | ||
84 | } else { | ||
85 | error = cmd_results_new(CMD_FAILURE, "split", | ||
86 | "Invalid split command (expected either horizontal or vertical)."); | ||
87 | return error; | ||
88 | } | ||
89 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
90 | } | ||
91 | |||
92 | struct cmd_results *cmd_splitv(int argc, char **argv) { | ||
93 | return _do_split(argc, argv, L_VERT); | ||
94 | } | ||
95 | |||
96 | struct cmd_results *cmd_splith(int argc, char **argv) { | ||
97 | return _do_split(argc, argv, L_HORIZ); | ||
98 | } | ||
99 | |||
100 | struct cmd_results *cmd_splitt(int argc, char **argv) { | ||
101 | struct sway_container *focused = config->handler_context.current_container; | ||
102 | if (focused->parent->layout == L_VERT) { | ||
103 | return _do_split(argc, argv, L_HORIZ); | ||
104 | } else { | ||
105 | return _do_split(argc, argv, L_VERT); | ||
106 | } | ||
107 | } | ||
diff --git a/sway/input/seat.c b/sway/input/seat.c index 9aa34aca..e0fd314a 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #define _XOPEN_SOURCE 700 | 1 | #define _XOPEN_SOURCE 700 |
2 | #include <assert.h> | ||
2 | #include <wlr/types/wlr_cursor.h> | 3 | #include <wlr/types/wlr_cursor.h> |
3 | #include <wlr/types/wlr_output_layout.h> | 4 | #include <wlr/types/wlr_output_layout.h> |
4 | #include <wlr/types/wlr_xcursor_manager.h> | 5 | #include <wlr/types/wlr_xcursor_manager.h> |
@@ -378,6 +379,18 @@ void sway_seat_set_focus(struct sway_seat *seat, | |||
378 | } | 379 | } |
379 | 380 | ||
380 | struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { | 381 | struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { |
382 | return sway_seat_get_focus_by_type(seat, container, C_TYPES); | ||
383 | } | ||
384 | |||
385 | struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { | ||
386 | if (!seat->has_focus) { | ||
387 | return NULL; | ||
388 | } | ||
389 | return sway_seat_get_focus_inactive(seat, &root_container); | ||
390 | } | ||
391 | |||
392 | struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, | ||
393 | struct sway_container *container, enum sway_container_type type) { | ||
381 | struct sway_seat_container *current = NULL; | 394 | struct sway_seat_container *current = NULL; |
382 | struct sway_container *parent = NULL; | 395 | struct sway_container *parent = NULL; |
383 | wl_list_for_each(current, &seat->focus_stack, link) { | 396 | wl_list_for_each(current, &seat->focus_stack, link) { |
@@ -388,7 +401,7 @@ struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, stru | |||
388 | } | 401 | } |
389 | 402 | ||
390 | while (parent) { | 403 | while (parent) { |
391 | if (parent == container) { | 404 | if (parent == container && (type == C_TYPES || current->container->type == type)) { |
392 | return current->container; | 405 | return current->container; |
393 | } | 406 | } |
394 | parent = parent->parent; | 407 | parent = parent->parent; |
@@ -398,23 +411,6 @@ struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, stru | |||
398 | return NULL; | 411 | return NULL; |
399 | } | 412 | } |
400 | 413 | ||
401 | struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { | ||
402 | if (!seat->has_focus) { | ||
403 | return NULL; | ||
404 | } | ||
405 | return sway_seat_get_focus_inactive(seat, &root_container); | ||
406 | } | ||
407 | |||
408 | struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, | ||
409 | enum sway_container_type type) { | ||
410 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); | ||
411 | if (focus->type == type) { | ||
412 | return focus; | ||
413 | } | ||
414 | |||
415 | return container_parent(focus, type); | ||
416 | } | ||
417 | |||
418 | void sway_seat_set_config(struct sway_seat *seat, | 414 | void sway_seat_set_config(struct sway_seat *seat, |
419 | struct seat_config *seat_config) { | 415 | struct seat_config *seat_config) { |
420 | // clear configs | 416 | // clear configs |
diff --git a/sway/meson.build b/sway/meson.build index 0cc620ea..b4775d58 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -19,6 +19,7 @@ sway_sources = files( | |||
19 | 'commands/input.c', | 19 | 'commands/input.c', |
20 | 'commands/layout.c', | 20 | 'commands/layout.c', |
21 | 'commands/mode.c', | 21 | 'commands/mode.c', |
22 | 'commands/split.c', | ||
22 | 'commands/seat.c', | 23 | 'commands/seat.c', |
23 | 'commands/seat/attach.c', | 24 | 'commands/seat/attach.c', |
24 | 'commands/seat/fallback.c', | 25 | 'commands/seat/fallback.c', |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 746dbf1f..7b88cccb 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -38,7 +38,7 @@ static void notify_new_container(struct sway_container *container) { | |||
38 | ipc_event_window(container, "new"); | 38 | ipc_event_window(container, "new"); |
39 | } | 39 | } |
40 | 40 | ||
41 | static struct sway_container *container_create(enum sway_container_type type) { | 41 | struct sway_container *container_create(enum sway_container_type type) { |
42 | // next id starts at 1 because 0 is assigned to root_container in layout.c | 42 | // next id starts at 1 because 0 is assigned to root_container in layout.c |
43 | static size_t next_id = 1; | 43 | static size_t next_id = 1; |
44 | struct sway_container *c = calloc(1, sizeof(struct sway_container)); | 44 | struct sway_container *c = calloc(1, sizeof(struct sway_container)); |
@@ -66,13 +66,14 @@ struct sway_container *container_destroy(struct sway_container *cont) { | |||
66 | wl_signal_emit(&cont->events.destroy, cont); | 66 | wl_signal_emit(&cont->events.destroy, cont); |
67 | 67 | ||
68 | struct sway_container *parent = cont->parent; | 68 | struct sway_container *parent = cont->parent; |
69 | if (cont->children) { | 69 | if (cont->children != NULL) { |
70 | // remove children until there are no more, container_destroy calls | 70 | // remove children until there are no more, container_destroy calls |
71 | // container_remove_child, which removes child from this container | 71 | // container_remove_child, which removes child from this container |
72 | while (cont->children->length) { | 72 | while (cont->children->length != 0) { |
73 | container_destroy(cont->children->items[0]); | 73 | container_destroy(cont->children->items[0]); |
74 | } | 74 | } |
75 | list_free(cont->children); | 75 | list_free(cont->children); |
76 | cont->children = NULL; | ||
76 | } | 77 | } |
77 | if (cont->marks) { | 78 | if (cont->marks) { |
78 | list_foreach(cont->marks, free); | 79 | list_foreach(cont->marks, free); |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ce0682dc..62df19e9 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <assert.h> | ||
2 | #include <ctype.h> | 3 | #include <ctype.h> |
3 | #include <math.h> | 4 | #include <math.h> |
4 | #include <stdbool.h> | 5 | #include <stdbool.h> |
@@ -100,6 +101,8 @@ void container_add_child(struct sway_container *parent, | |||
100 | parent, parent->type, parent->width, parent->height); | 101 | parent, parent->type, parent->width, parent->height); |
101 | list_add(parent->children, child); | 102 | list_add(parent->children, child); |
102 | child->parent = parent; | 103 | child->parent = parent; |
104 | // TODO: set focus for this container? | ||
105 | sway_input_manager_set_focus(input_manager, child); | ||
103 | } | 106 | } |
104 | 107 | ||
105 | struct sway_container *container_reap_empty(struct sway_container *container) { | 108 | struct sway_container *container_reap_empty(struct sway_container *container) { |
@@ -135,7 +138,7 @@ struct sway_container *container_remove_child(struct sway_container *child) { | |||
135 | } | 138 | } |
136 | } | 139 | } |
137 | child->parent = NULL; | 140 | child->parent = NULL; |
138 | return container_reap_empty(parent); | 141 | return parent; |
139 | } | 142 | } |
140 | 143 | ||
141 | void container_move_to(struct sway_container* container, | 144 | void container_move_to(struct sway_container* container, |
@@ -322,7 +325,12 @@ static void apply_horiz_layout(struct sway_container *container, | |||
322 | wlr_log(L_DEBUG, | 325 | wlr_log(L_DEBUG, |
323 | "Calculating arrangement for %p:%d (will scale %f by %f)", | 326 | "Calculating arrangement for %p:%d (will scale %f by %f)", |
324 | child, child->type, width, scale); | 327 | child, child->type, width, scale); |
325 | view_set_position(child->sway_view, child_x, y); | 328 | if (child->type == C_VIEW) { |
329 | view_set_position(child->sway_view, child_x, y); | ||
330 | } else { | ||
331 | child->x = child_x; | ||
332 | child->y = y; | ||
333 | } | ||
326 | 334 | ||
327 | if (i == end - 1) { | 335 | if (i == end - 1) { |
328 | double remaining_width = x + width - child_x; | 336 | double remaining_width = x + width - child_x; |
@@ -505,9 +513,9 @@ static struct sway_container *sway_output_from_wlr(struct wlr_output *output) { | |||
505 | return NULL; | 513 | return NULL; |
506 | } | 514 | } |
507 | 515 | ||
508 | static struct sway_container *get_swayc_in_direction_under( | 516 | struct sway_container *container_get_in_direction( |
509 | struct sway_container *container, enum movement_direction dir, | 517 | struct sway_container *container, struct sway_seat *seat, |
510 | struct sway_seat *seat, struct sway_container *limit) { | 518 | enum movement_direction dir) { |
511 | if (dir == MOVE_CHILD) { | 519 | if (dir == MOVE_CHILD) { |
512 | return sway_seat_get_focus_inactive(seat, container); | 520 | return sway_seat_get_focus_inactive(seat, container); |
513 | } | 521 | } |
@@ -559,7 +567,6 @@ static struct sway_container *get_swayc_in_direction_under( | |||
559 | 567 | ||
560 | struct sway_container *wrap_candidate = NULL; | 568 | struct sway_container *wrap_candidate = NULL; |
561 | while (true) { | 569 | while (true) { |
562 | // Test if we can even make a difference here | ||
563 | bool can_move = false; | 570 | bool can_move = false; |
564 | int desired; | 571 | int desired; |
565 | int idx = index_child(container); | 572 | int idx = index_child(container); |
@@ -589,7 +596,7 @@ static struct sway_container *get_swayc_in_direction_under( | |||
589 | } | 596 | } |
590 | if (next->children && next->children->length) { | 597 | if (next->children && next->children->length) { |
591 | // TODO consider floating children as well | 598 | // TODO consider floating children as well |
592 | return sway_seat_get_focus_inactive(seat, next); | 599 | return sway_seat_get_focus_by_type(seat, next, C_VIEW); |
593 | } else { | 600 | } else { |
594 | return next; | 601 | return next; |
595 | } | 602 | } |
@@ -619,21 +626,22 @@ static struct sway_container *get_swayc_in_direction_under( | |||
619 | wrap_candidate = parent->children->items[0]; | 626 | wrap_candidate = parent->children->items[0]; |
620 | } | 627 | } |
621 | if (config->force_focus_wrapping) { | 628 | if (config->force_focus_wrapping) { |
622 | return wrap_candidate; | 629 | return sway_seat_get_focus_by_type(seat, wrap_candidate, C_VIEW); |
623 | } | 630 | } |
624 | } | 631 | } |
625 | } else { | 632 | } else { |
626 | wlr_log(L_DEBUG, | 633 | wlr_log(L_DEBUG, |
627 | "cont %d-%p dir %i sibling %d: %p", idx, | 634 | "cont %d-%p dir %i sibling %d: %p", idx, |
628 | container, dir, desired, parent->children->items[desired]); | 635 | container, dir, desired, parent->children->items[desired]); |
629 | return parent->children->items[desired]; | 636 | return sway_seat_get_focus_by_type(seat, |
637 | parent->children->items[desired], C_VIEW); | ||
630 | } | 638 | } |
631 | } | 639 | } |
632 | 640 | ||
633 | if (!can_move) { | 641 | if (!can_move) { |
634 | container = parent; | 642 | container = parent; |
635 | parent = parent->parent; | 643 | parent = parent->parent; |
636 | if (!parent || container == limit) { | 644 | if (!parent) { |
637 | // wrapping is the last chance | 645 | // wrapping is the last chance |
638 | return wrap_candidate; | 646 | return wrap_candidate; |
639 | } | 647 | } |
@@ -641,8 +649,71 @@ static struct sway_container *get_swayc_in_direction_under( | |||
641 | } | 649 | } |
642 | } | 650 | } |
643 | 651 | ||
644 | struct sway_container *container_get_in_direction( | 652 | struct sway_container *container_replace_child(struct sway_container *child, |
645 | struct sway_container *container, struct sway_seat *seat, | 653 | struct sway_container *new_child) { |
646 | enum movement_direction dir) { | 654 | struct sway_container *parent = child->parent; |
647 | return get_swayc_in_direction_under(container, dir, seat, NULL); | 655 | if (parent == NULL) { |
656 | return NULL; | ||
657 | } | ||
658 | int i = index_child(child); | ||
659 | |||
660 | // TODO floating | ||
661 | parent->children->items[i] = new_child; | ||
662 | new_child->parent = parent; | ||
663 | child->parent = NULL; | ||
664 | |||
665 | // Set geometry for new child | ||
666 | new_child->x = child->x; | ||
667 | new_child->y = child->y; | ||
668 | new_child->width = child->width; | ||
669 | new_child->height = child->height; | ||
670 | |||
671 | // reset geometry for child | ||
672 | child->width = 0; | ||
673 | child->height = 0; | ||
674 | |||
675 | return parent; | ||
676 | } | ||
677 | |||
678 | struct sway_container *container_split(struct sway_container *child, | ||
679 | enum sway_container_layout layout) { | ||
680 | // TODO floating: cannot split a floating container | ||
681 | if (!sway_assert(child, "child cannot be null")) { | ||
682 | return NULL; | ||
683 | } | ||
684 | struct sway_container *cont = container_create(C_CONTAINER); | ||
685 | |||
686 | wlr_log(L_DEBUG, "creating container %p around %p", cont, child); | ||
687 | |||
688 | cont->prev_layout = L_NONE; | ||
689 | cont->layout = layout; | ||
690 | cont->width = child->width; | ||
691 | cont->height = child->height; | ||
692 | cont->x = child->x; | ||
693 | cont->y = child->y; | ||
694 | |||
695 | /* Container inherits all of workspaces children, layout and whatnot */ | ||
696 | if (child->type == C_WORKSPACE) { | ||
697 | struct sway_container *workspace = child; | ||
698 | // reorder focus | ||
699 | int i; | ||
700 | for (i = 0; i < workspace->children->length; ++i) { | ||
701 | ((struct sway_container *)workspace->children->items[i])->parent = | ||
702 | cont; | ||
703 | } | ||
704 | |||
705 | // Swap children | ||
706 | list_t *tmp_list = workspace->children; | ||
707 | workspace->children = cont->children; | ||
708 | cont->children = tmp_list; | ||
709 | // add container to workspace chidren | ||
710 | container_add_child(workspace, cont); | ||
711 | // give them proper layouts | ||
712 | cont->layout = workspace->workspace_layout; | ||
713 | cont->prev_layout = workspace->prev_layout; | ||
714 | } else { // Or is built around container | ||
715 | container_replace_child(child, cont); | ||
716 | container_add_child(cont, child); | ||
717 | } | ||
718 | return cont; | ||
648 | } | 719 | } |