summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/input/seat.h2
-rw-r--r--include/sway/tree/container.h2
-rw-r--r--include/sway/tree/layout.h3
-rw-r--r--sway/commands.c4
-rw-r--r--sway/commands/kill.c29
-rw-r--r--sway/commands/split.c107
-rw-r--r--sway/input/seat.c32
-rw-r--r--sway/meson.build1
-rw-r--r--sway/tree/container.c7
-rw-r--r--sway/tree/layout.c99
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
76struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, 76struct 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
79void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); 79void 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
90struct 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?
91struct sway_container *container_output_create( 93struct 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,
54struct sway_container *container_get_in_direction(struct sway_container 54struct 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
57struct 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
168static int handler_compare(const void *_a, const void *_b) { 172static 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
8struct cmd_results *cmd_kill(int argc, char **argv) { 9struct 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
11static 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
57struct 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
92struct cmd_results *cmd_splitv(int argc, char **argv) {
93 return _do_split(argc, argv, L_VERT);
94}
95
96struct cmd_results *cmd_splith(int argc, char **argv) {
97 return _do_split(argc, argv, L_HORIZ);
98}
99
100struct 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
380struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { 381struct 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
385struct 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
392struct 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
401struct 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
408struct 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
418void sway_seat_set_config(struct sway_seat *seat, 414void 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
41static struct sway_container *container_create(enum sway_container_type type) { 41struct 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
105struct sway_container *container_reap_empty(struct sway_container *container) { 108struct 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
141void container_move_to(struct sway_container* container, 144void 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
508static struct sway_container *get_swayc_in_direction_under( 516struct 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
644struct sway_container *container_get_in_direction( 652struct 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
678struct 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}