summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/pool-buffer.c2
-rw-r--r--include/sway/config.h1
-rw-r--r--include/sway/input/seat.h3
-rw-r--r--include/sway/output.h2
-rw-r--r--include/sway/tree/container.h5
-rw-r--r--include/sway/tree/layout.h12
-rw-r--r--sway/commands.c3
-rw-r--r--sway/commands/focus.c7
-rw-r--r--sway/commands/focus_follows_mouse.c12
-rw-r--r--sway/commands/mouse_warping.c19
-rw-r--r--sway/commands/move.c184
-rw-r--r--sway/config.c1
-rw-r--r--sway/desktop/layer_shell.c5
-rw-r--r--sway/desktop/output.c34
-rw-r--r--sway/desktop/xwayland.c18
-rw-r--r--sway/input/cursor.c70
-rw-r--r--sway/input/keyboard.c4
-rw-r--r--sway/input/seat.c36
-rw-r--r--sway/meson.build3
-rw-r--r--sway/server.c15
-rw-r--r--sway/tree/container.c18
-rw-r--r--sway/tree/layout.c58
-rw-r--r--sway/tree/output.c11
23 files changed, 430 insertions, 93 deletions
diff --git a/client/pool-buffer.c b/client/pool-buffer.c
index 93cfcfc5..b5ed9c98 100644
--- a/client/pool-buffer.c
+++ b/client/pool-buffer.c
@@ -57,7 +57,7 @@ static struct pool_buffer *create_buffer(struct wl_shm *shm,
57 57
58 char *name; 58 char *name;
59 int fd = create_pool_file(size, &name); 59 int fd = create_pool_file(size, &name);
60 assert(fd); 60 assert(fd != -1);
61 void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 61 void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
62 struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); 62 struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size);
63 buf->buffer = wl_shm_pool_create_buffer(pool, 0, 63 buf->buffer = wl_shm_pool_create_buffer(pool, 0,
diff --git a/include/sway/config.h b/include/sway/config.h
index ac1105b4..03b51948 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -304,7 +304,6 @@ struct sway_config {
304 bool reloading; 304 bool reloading;
305 bool reading; 305 bool reading;
306 bool auto_back_and_forth; 306 bool auto_back_and_forth;
307 bool seamless_mouse;
308 bool show_marks; 307 bool show_marks;
309 308
310 bool edge_gaps; 309 bool edge_gaps;
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h
index 496bfd5d..31210a5a 100644
--- a/include/sway/input/seat.h
+++ b/include/sway/input/seat.h
@@ -56,6 +56,9 @@ void sway_seat_configure_xcursor(struct sway_seat *seat);
56 56
57void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); 57void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container);
58 58
59void sway_seat_set_focus_warp(struct sway_seat *seat,
60 struct sway_container *container, bool warp);
61
59struct sway_container *sway_seat_get_focus(struct sway_seat *seat); 62struct sway_container *sway_seat_get_focus(struct sway_seat *seat);
60 63
61/** 64/**
diff --git a/include/sway/output.h b/include/sway/output.h
index b4980cd8..b343ecff 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -36,4 +36,6 @@ void output_damage_whole(struct sway_output *output);
36void output_damage_whole_view(struct sway_output *output, 36void output_damage_whole_view(struct sway_output *output,
37 struct sway_view *view); 37 struct sway_view *view);
38 38
39struct sway_container *output_by_name(const char *name);
40
39#endif 41#endif
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index 6aa66da0..aff2e58e 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -84,9 +84,14 @@ struct sway_container {
84 84
85 struct { 85 struct {
86 struct wl_signal destroy; 86 struct wl_signal destroy;
87 // Raised after the tree updates, but before arrange_windows
88 // Passed the previous parent
89 struct wl_signal reparent;
87 } events; 90 } events;
88}; 91};
89 92
93const char *container_type_to_str(enum sway_container_type type);
94
90// TODO only one container create function and pass the type? 95// TODO only one container create function and pass the type?
91struct sway_container *container_output_create( 96struct sway_container *container_output_create(
92 struct sway_output *sway_output); 97 struct sway_output *sway_output);
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h
index 0a904c4b..e1034657 100644
--- a/include/sway/tree/layout.h
+++ b/include/sway/tree/layout.h
@@ -11,9 +11,6 @@ enum movement_direction {
11 MOVE_DOWN, 11 MOVE_DOWN,
12 MOVE_PARENT, 12 MOVE_PARENT,
13 MOVE_CHILD, 13 MOVE_CHILD,
14 MOVE_NEXT,
15 MOVE_PREV,
16 MOVE_FIRST
17}; 14};
18 15
19struct sway_container; 16struct sway_container;
@@ -32,7 +29,8 @@ struct sway_root {
32 29
33void layout_init(void); 30void layout_init(void);
34 31
35void container_add_child(struct sway_container *parent, struct sway_container *child); 32void container_add_child(struct sway_container *parent,
33 struct sway_container *child);
36 34
37struct sway_container *container_add_sibling(struct sway_container *parent, 35struct sway_container *container_add_sibling(struct sway_container *parent,
38 struct sway_container *child); 36 struct sway_container *child);
@@ -44,7 +42,11 @@ struct sway_container *container_reap_empty(struct sway_container *container);
44void container_move_to(struct sway_container* container, 42void container_move_to(struct sway_container* container,
45 struct sway_container* destination); 43 struct sway_container* destination);
46 44
47enum sway_container_layout container_get_default_layout(struct sway_container *output); 45void container_move(struct sway_container *container,
46 enum movement_direction dir, int move_amt);
47
48enum sway_container_layout container_get_default_layout(
49 struct sway_container *output);
48 50
49void container_sort_workspaces(struct sway_container *output); 51void container_sort_workspaces(struct sway_container *output);
50 52
diff --git a/sway/commands.c b/sway/commands.c
index eee7f254..b6af3d1a 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -98,9 +98,11 @@ static struct cmd_handler handlers[] = {
98 { "bindsym", cmd_bindsym }, 98 { "bindsym", cmd_bindsym },
99 { "exec", cmd_exec }, 99 { "exec", cmd_exec },
100 { "exec_always", cmd_exec_always }, 100 { "exec_always", cmd_exec_always },
101 { "focus_follows_mouse", cmd_focus_follows_mouse },
101 { "include", cmd_include }, 102 { "include", cmd_include },
102 { "input", cmd_input }, 103 { "input", cmd_input },
103 { "mode", cmd_mode }, 104 { "mode", cmd_mode },
105 { "mouse_warping", cmd_mouse_warping },
104 { "output", cmd_output }, 106 { "output", cmd_output },
105 { "seat", cmd_seat }, 107 { "seat", cmd_seat },
106 { "workspace", cmd_workspace }, 108 { "workspace", cmd_workspace },
@@ -160,6 +162,7 @@ static struct cmd_handler command_handlers[] = {
160 { "focus", cmd_focus }, 162 { "focus", cmd_focus },
161 { "kill", cmd_kill }, 163 { "kill", cmd_kill },
162 { "layout", cmd_layout }, 164 { "layout", cmd_layout },
165 { "move", cmd_move },
163 { "reload", cmd_reload }, 166 { "reload", cmd_reload },
164}; 167};
165 168
diff --git a/sway/commands/focus.c b/sway/commands/focus.c
index 64f079f4..0a521b9e 100644
--- a/sway/commands/focus.c
+++ b/sway/commands/focus.c
@@ -20,10 +20,6 @@ static bool parse_movement_direction(const char *name,
20 *out = MOVE_PARENT; 20 *out = MOVE_PARENT;
21 } else if (strcasecmp(name, "child") == 0) { 21 } else if (strcasecmp(name, "child") == 0) {
22 *out = MOVE_CHILD; 22 *out = MOVE_CHILD;
23 } else if (strcasecmp(name, "next") == 0) {
24 *out = MOVE_NEXT;
25 } else if (strcasecmp(name, "prev") == 0) {
26 *out = MOVE_PREV;
27 } else { 23 } else {
28 return false; 24 return false;
29 } 25 }
@@ -51,7 +47,8 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
51 "Expected 'focus <direction|parent|child|mode_toggle>' or 'focus output <direction|name>'"); 47 "Expected 'focus <direction|parent|child|mode_toggle>' or 'focus output <direction|name>'");
52 } 48 }
53 49
54 struct sway_container *next_focus = container_get_in_direction(con, seat, direction); 50 struct sway_container *next_focus = container_get_in_direction(
51 con, seat, direction);
55 if (next_focus) { 52 if (next_focus) {
56 sway_seat_set_focus(seat, next_focus); 53 sway_seat_set_focus(seat, next_focus);
57 } 54 }
diff --git a/sway/commands/focus_follows_mouse.c b/sway/commands/focus_follows_mouse.c
new file mode 100644
index 00000000..661e7852
--- /dev/null
+++ b/sway/commands/focus_follows_mouse.c
@@ -0,0 +1,12 @@
1#include <string.h>
2#include <strings.h>
3#include "sway/commands.h"
4
5struct cmd_results *cmd_focus_follows_mouse(int argc, char **argv) {
6 struct cmd_results *error = NULL;
7 if ((error = checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1))) {
8 return error;
9 }
10 config->focus_follows_mouse = !strcasecmp(argv[0], "yes");
11 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
12}
diff --git a/sway/commands/mouse_warping.c b/sway/commands/mouse_warping.c
new file mode 100644
index 00000000..eef32ce7
--- /dev/null
+++ b/sway/commands/mouse_warping.c
@@ -0,0 +1,19 @@
1#include <string.h>
2#include <strings.h>
3#include "sway/commands.h"
4
5struct cmd_results *cmd_mouse_warping(int argc, char **argv) {
6 struct cmd_results *error = NULL;
7 if ((error = checkarg(argc, "mouse_warping", EXPECTED_EQUAL_TO, 1))) {
8 return error;
9 } else if (strcasecmp(argv[0], "output") == 0) {
10 config->mouse_warping = true;
11 } else if (strcasecmp(argv[0], "none") == 0) {
12 config->mouse_warping = false;
13 } else {
14 return cmd_results_new(CMD_FAILURE, "mouse_warping",
15 "Expected 'mouse_warping output|none'");
16 }
17 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
18}
19
diff --git a/sway/commands/move.c b/sway/commands/move.c
new file mode 100644
index 00000000..ab959b77
--- /dev/null
+++ b/sway/commands/move.c
@@ -0,0 +1,184 @@
1#include <string.h>
2#include <strings.h>
3#include <wlr/types/wlr_output.h>
4#include <wlr/types/wlr_output_layout.h>
5#include <wlr/util/log.h>
6#include "sway/commands.h"
7#include "sway/input/seat.h"
8#include "sway/output.h"
9#include "sway/tree/container.h"
10#include "sway/tree/layout.h"
11#include "sway/tree/workspace.h"
12#include "stringop.h"
13#include "list.h"
14
15static const char* expected_syntax =
16 "Expected 'move <left|right|up|down> <[px] px>' or "
17 "'move <container|window> to workspace <name>' or "
18 "'move <container|window|workspace> to output <name|direction>' or "
19 "'move position mouse'";
20
21static struct sway_container *output_in_direction(const char *direction,
22 struct wlr_output *reference, int ref_ox, int ref_oy) {
23 int ref_lx = ref_ox + reference->lx,
24 ref_ly = ref_oy + reference->ly;
25 struct {
26 char *name;
27 enum wlr_direction direction;
28 } names[] = {
29 { "up", WLR_DIRECTION_UP },
30 { "down", WLR_DIRECTION_DOWN },
31 { "left", WLR_DIRECTION_LEFT },
32 { "right", WLR_DIRECTION_RIGHT },
33 };
34 for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); ++i) {
35 if (strcasecmp(names[i].name, direction) == 0) {
36 struct wlr_output *adjacent = wlr_output_layout_adjacent_output(
37 root_container.sway_root->output_layout,
38 names[i].direction, reference, ref_lx, ref_ly);
39 if (adjacent) {
40 struct sway_output *sway_output = adjacent->data;
41 return sway_output->swayc;
42 }
43 break;
44 }
45 }
46 return output_by_name(direction);
47}
48
49static struct cmd_results *cmd_move_container(struct sway_container *current,
50 int argc, char **argv) {
51 struct cmd_results *error = NULL;
52 if ((error = checkarg(argc, "move container/window",
53 EXPECTED_AT_LEAST, 4))) {
54 return error;
55 } else if (strcasecmp(argv[1], "to") == 0
56 && strcasecmp(argv[2], "workspace") == 0) {
57 // move container to workspace x
58 if (current->type == C_WORKSPACE) {
59 // TODO: Wrap children in a container and move that
60 return cmd_results_new(CMD_FAILURE, "move", "Unimplemented");
61 } else if (current->type != C_CONTAINER && current->type != C_VIEW) {
62 return cmd_results_new(CMD_FAILURE, "move",
63 "Can only move containers and views.");
64 }
65 struct sway_container *ws;
66 const char *num_name = NULL;
67 char *ws_name = NULL;
68 if (argc == 5 && strcasecmp(argv[3], "number") == 0) {
69 // move "container to workspace number x"
70 num_name = argv[4];
71 ws = workspace_by_number(num_name);
72 } else {
73 ws_name = join_args(argv + 3, argc - 3);
74 ws = workspace_by_name(ws_name);
75 }
76 if (!ws) {
77 ws = workspace_create(ws_name ? ws_name : num_name);
78 }
79 free(ws_name);
80 struct sway_container *old_parent = current->parent;
81 struct sway_container *focus = sway_seat_get_focus_inactive(
82 config->handler_context.seat, ws);
83 container_move_to(current, focus);
84 sway_seat_set_focus(config->handler_context.seat, old_parent);
85 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
86 } else if (strcasecmp(argv[1], "to") == 0
87 && strcasecmp(argv[2], "output") == 0) {
88 if (current->type == C_WORKSPACE) {
89 // TODO: Wrap children in a container and move that
90 return cmd_results_new(CMD_FAILURE, "move", "Unimplemented");
91 } else if (current->type != C_CONTAINER
92 && current->type != C_VIEW) {
93 return cmd_results_new(CMD_FAILURE, "move",
94 "Can only move containers and views.");
95 }
96 struct sway_container *source = container_parent(current, C_OUTPUT);
97 struct sway_container *destination = output_in_direction(argv[3],
98 source->sway_output->wlr_output, current->x, current->y);
99 if (!destination) {
100 return cmd_results_new(CMD_FAILURE, "move workspace",
101 "Can't find output with name/direction '%s'", argv[3]);
102 }
103 struct sway_container *focus = sway_seat_get_focus_inactive(
104 config->handler_context.seat, destination);
105 if (!focus) {
106 // We've never been to this output before
107 focus = destination->children->items[0];
108 }
109 struct sway_container *old_parent = current->parent;
110 container_move_to(current, focus);
111 sway_seat_set_focus(config->handler_context.seat, old_parent);
112 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
113 }
114 return cmd_results_new(CMD_INVALID, "move", expected_syntax);
115}
116
117static struct cmd_results *cmd_move_workspace(struct sway_container *current,
118 int argc, char **argv) {
119 struct cmd_results *error = NULL;
120 if ((error = checkarg(argc, "move workspace", EXPECTED_EQUAL_TO, 4))) {
121 return error;
122 } else if (strcasecmp(argv[1], "to") != 0
123 || strcasecmp(argv[2], "output") != 0) {
124 return cmd_results_new(CMD_INVALID, "move", expected_syntax);
125 }
126 struct sway_container *source = container_parent(current, C_OUTPUT);
127 int center_x = current->width / 2 + current->x,
128 center_y = current->height / 2 + current->y;
129 struct sway_container *destination = output_in_direction(argv[3],
130 source->sway_output->wlr_output, center_x, center_y);
131 if (!destination) {
132 return cmd_results_new(CMD_FAILURE, "move workspace",
133 "Can't find output with name/direction '%s'", argv[3]);
134 }
135 if (current->type != C_WORKSPACE) {
136 current = container_parent(current, C_WORKSPACE);
137 }
138 container_move_to(current, destination);
139 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
140}
141
142struct cmd_results *cmd_move(int argc, char **argv) {
143 struct cmd_results *error = NULL;
144 int move_amt = 10;
145 if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) {
146 return error;
147 }
148 struct sway_container *current = config->handler_context.current_container;
149
150 if (argc == 2 || (argc == 3 && strcasecmp(argv[2], "px") == 0)) {
151 char *inv;
152 move_amt = (int)strtol(argv[1], &inv, 10);
153 if (*inv != '\0' && strcasecmp(inv, "px") != 0) {
154 return cmd_results_new(CMD_FAILURE, "move",
155 "Invalid distance specified");
156 }
157 }
158
159 if (strcasecmp(argv[0], "left") == 0) {
160 container_move(current, MOVE_LEFT, move_amt);
161 } else if (strcasecmp(argv[0], "right") == 0) {
162 container_move(current, MOVE_RIGHT, move_amt);
163 } else if (strcasecmp(argv[0], "up") == 0) {
164 container_move(current, MOVE_UP, move_amt);
165 } else if (strcasecmp(argv[0], "down") == 0) {
166 container_move(current, MOVE_DOWN, move_amt);
167 } else if (strcasecmp(argv[0], "container") == 0
168 || strcasecmp(argv[0], "window") == 0) {
169 return cmd_move_container(current, argc, argv);
170 } else if (strcasecmp(argv[0], "workspace") == 0) {
171 return cmd_move_workspace(current, argc, argv);
172 } else if (strcasecmp(argv[0], "scratchpad") == 0
173 || (strcasecmp(argv[0], "to") == 0
174 && strcasecmp(argv[1], "scratchpad") == 0)) {
175 // TODO: scratchpad
176 return cmd_results_new(CMD_FAILURE, "move", "Unimplemented");
177 } else if (strcasecmp(argv[0], "position") == 0) {
178 // TODO: floating
179 return cmd_results_new(CMD_FAILURE, "move", "Unimplemented");
180 } else {
181 return cmd_results_new(CMD_INVALID, "move", expected_syntax);
182 }
183 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
184}
diff --git a/sway/config.c b/sway/config.c
index e9e7057d..0eecf7f6 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -178,7 +178,6 @@ static void config_defaults(struct sway_config *config) {
178 config->active = false; 178 config->active = false;
179 config->failed = false; 179 config->failed = false;
180 config->auto_back_and_forth = false; 180 config->auto_back_and_forth = false;
181 config->seamless_mouse = true;
182 config->reading = false; 181 config->reading = false;
183 config->show_marks = true; 182 config->show_marks = true;
184 183
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index 5c96659a..c18f51c7 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -238,11 +238,12 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
238 wl_list_remove(&sway_layer->unmap.link); 238 wl_list_remove(&sway_layer->unmap.link);
239 wl_list_remove(&sway_layer->surface_commit.link); 239 wl_list_remove(&sway_layer->surface_commit.link);
240 if (sway_layer->layer_surface->output != NULL) { 240 if (sway_layer->layer_surface->output != NULL) {
241 struct sway_output *output = sway_layer->layer_surface->output->data;
242 arrange_layers(output);
243
241 wl_list_remove(&sway_layer->output_destroy.link); 244 wl_list_remove(&sway_layer->output_destroy.link);
242 } 245 }
243 struct sway_output *output = sway_layer->layer_surface->output->data;
244 free(sway_layer); 246 free(sway_layer);
245 arrange_layers(output);
246} 247}
247 248
248static void handle_map(struct wl_listener *listener, void *data) { 249static void handle_map(struct wl_listener *listener, void *data) {
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index c248b29e..c4265818 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -229,9 +229,12 @@ static void render_output(struct sway_output *output, struct timespec *when,
229 struct sway_seat *seat = input_manager_current_seat(input_manager); 229 struct sway_seat *seat = input_manager_current_seat(input_manager);
230 struct sway_container *focus = 230 struct sway_container *focus =
231 sway_seat_get_focus_inactive(seat, output->swayc); 231 sway_seat_get_focus_inactive(seat, output->swayc);
232 struct sway_container *workspace = (focus->type == C_WORKSPACE ? 232 if (!focus) {
233 focus : 233 // We've never been to this output before
234 container_parent(focus, C_WORKSPACE)); 234 focus = output->swayc->children->items[0];
235 }
236 struct sway_container *workspace = focus->type == C_WORKSPACE ?
237 focus : container_parent(focus, C_WORKSPACE);
235 238
236 struct render_data rdata = { 239 struct render_data rdata = {
237 .output = output, 240 .output = output,
@@ -243,14 +246,25 @@ static void render_output(struct sway_output *output, struct timespec *when,
243 struct sway_view *view; 246 struct sway_view *view;
244 wl_list_for_each(view, &root_container.sway_root->unmanaged_views, 247 wl_list_for_each(view, &root_container.sway_root->unmanaged_views,
245 unmanaged_view_link) { 248 unmanaged_view_link) {
246 if (view->type == SWAY_XWAYLAND_VIEW) { 249 if (view->type != SWAY_XWAYLAND_VIEW) {
247 // the only kind of unamanged view right now is xwayland override 250 continue;
248 // redirect 251 }
249 int view_x = view->wlr_xwayland_surface->x; 252
250 int view_y = view->wlr_xwayland_surface->y; 253 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
251 render_surface(view->surface, wlr_output, &output->last_frame, 254
252 view_x, view_y, 0); 255 const struct wlr_box view_box = {
256 .x = xsurface->x,
257 .y = xsurface->y,
258 .width = xsurface->width,
259 .height = xsurface->height,
260 };
261 struct wlr_box intersection;
262 if (!wlr_box_intersection(&view_box, output_box, &intersection)) {
263 continue;
253 } 264 }
265
266 render_surface(view->surface, wlr_output, &output->last_frame,
267 view_box.x - output_box->x, view_box.y - output_box->y, 0);
254 } 268 }
255 269
256 // TODO: Consider revising this when fullscreen windows are supported 270 // TODO: Consider revising this when fullscreen windows are supported
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 01c993b3..273ca2bf 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -41,7 +41,7 @@ static void set_size(struct sway_view *view, int width, int height) {
41 view->sway_xwayland_surface->pending_height = height; 41 view->sway_xwayland_surface->pending_height = height;
42 42
43 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 43 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
44 wlr_xwayland_surface_configure(xsurface, view->swayc->x, view->swayc->y, 44 wlr_xwayland_surface_configure(xsurface, xsurface->x, xsurface->y,
45 width, height); 45 width, height);
46} 46}
47 47
@@ -67,13 +67,10 @@ static void set_position(struct sway_view *view, double ox, double oy) {
67 view->swayc->x = ox; 67 view->swayc->x = ox;
68 view->swayc->y = oy; 68 view->swayc->y = oy;
69 69
70 if (view->width == 0 || view->height == 0) {
71 return;
72 }
73
74 wlr_xwayland_surface_configure(view->wlr_xwayland_surface, 70 wlr_xwayland_surface_configure(view->wlr_xwayland_surface,
75 ox + loutput->x, oy + loutput->y, 71 ox + loutput->x, oy + loutput->y,
76 view->width, view->height); 72 view->wlr_xwayland_surface->width,
73 view->wlr_xwayland_surface->height);
77} 74}
78 75
79static void set_activated(struct sway_view *view, bool activated) { 76static void set_activated(struct sway_view *view, bool activated) {
@@ -143,8 +140,11 @@ static void handle_map(struct wl_listener *listener, void *data) {
143 struct sway_view *view = sway_surface->view; 140 struct sway_view *view = sway_surface->view;
144 container_view_destroy(view->swayc); 141 container_view_destroy(view->swayc);
145 142
143 wlr_xwayland_surface_set_maximized(xsurface, true);
144
146 struct sway_seat *seat = input_manager_current_seat(input_manager); 145 struct sway_seat *seat = input_manager_current_seat(input_manager);
147 struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); 146 struct sway_container *focus = sway_seat_get_focus_inactive(seat,
147 &root_container);
148 struct sway_container *cont = container_view_create(focus, view); 148 struct sway_container *cont = container_view_create(focus, view);
149 view->swayc = cont; 149 view->swayc = cont;
150 arrange_windows(cont->parent, -1, -1); 150 arrange_windows(cont->parent, -1, -1);
@@ -154,7 +154,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
154 view_damage_whole(sway_surface->view); 154 view_damage_whole(sway_surface->view);
155} 155}
156 156
157static void handle_configure_request(struct wl_listener *listener, void *data) { 157static void handle_request_configure(struct wl_listener *listener, void *data) {
158 struct sway_xwayland_surface *sway_surface = 158 struct sway_xwayland_surface *sway_surface =
159 wl_container_of(listener, sway_surface, request_configure); 159 wl_container_of(listener, sway_surface, request_configure);
160 struct wlr_xwayland_surface_configure_event *ev = data; 160 struct wlr_xwayland_surface_configure_event *ev = data;
@@ -209,7 +209,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
209 209
210 wl_signal_add(&xsurface->events.request_configure, 210 wl_signal_add(&xsurface->events.request_configure,
211 &sway_surface->request_configure); 211 &sway_surface->request_configure);
212 sway_surface->request_configure.notify = handle_configure_request; 212 sway_surface->request_configure.notify = handle_request_configure;
213 213
214 wl_signal_add(&xsurface->events.unmap, &sway_surface->unmap); 214 wl_signal_add(&xsurface->events.unmap, &sway_surface->unmap);
215 sway_surface->unmap.notify = handle_unmap; 215 sway_surface->unmap.notify = handle_unmap;
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 7390816f..d608a9cf 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -50,21 +50,23 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor,
50 struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views; 50 struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views;
51 struct sway_view *view; 51 struct sway_view *view;
52 wl_list_for_each_reverse(view, unmanaged, unmanaged_view_link) { 52 wl_list_for_each_reverse(view, unmanaged, unmanaged_view_link) {
53 if (view->type == SWAY_XWAYLAND_VIEW) { 53 if (view->type != SWAY_XWAYLAND_VIEW) {
54 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 54 continue;
55 struct wlr_box box = { 55 }
56 .x = xsurface->x, 56
57 .y = xsurface->y, 57 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
58 .width = xsurface->width, 58 struct wlr_box box = {
59 .height = xsurface->height, 59 .x = xsurface->x,
60 }; 60 .y = xsurface->y,
61 61 .width = xsurface->width,
62 if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { 62 .height = xsurface->height,
63 *surface = xsurface->surface; 63 };
64 *sx = cursor->x - box.x; 64
65 *sy = cursor->y - box.y; 65 if (wlr_box_contains_point(&box, cursor->x, cursor->y)) {
66 return view->swayc; 66 *surface = xsurface->surface;
67 } 67 *sx = cursor->x - box.x;
68 *sy = cursor->y - box.y;
69 return NULL;
68 } 70 }
69 } 71 }
70 72
@@ -125,7 +127,10 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor,
125 struct wlr_seat *seat = cursor->seat->wlr_seat; 127 struct wlr_seat *seat = cursor->seat->wlr_seat;
126 struct wlr_surface *surface = NULL; 128 struct wlr_surface *surface = NULL;
127 double sx, sy; 129 double sx, sy;
128 container_at_cursor(cursor, &surface, &sx, &sy); 130 struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy);
131 if (c && config->focus_follows_mouse) {
132 sway_seat_set_focus_warp(cursor->seat, c, false);
133 }
129 134
130 // reset cursor if switching between clients 135 // reset cursor if switching between clients
131 struct wl_client *client = NULL; 136 struct wl_client *client = NULL;
@@ -156,8 +161,8 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) {
156 cursor_send_pointer_motion(cursor, event->time_msec); 161 cursor_send_pointer_motion(cursor, event->time_msec);
157} 162}
158 163
159static void handle_cursor_motion_absolute(struct wl_listener *listener, 164static void handle_cursor_motion_absolute(
160 void *data) { 165 struct wl_listener *listener, void *data) {
161 struct sway_cursor *cursor = 166 struct sway_cursor *cursor =
162 wl_container_of(listener, cursor, motion_absolute); 167 wl_container_of(listener, cursor, motion_absolute);
163 struct wlr_event_pointer_motion_absolute *event = data; 168 struct wlr_event_pointer_motion_absolute *event = data;
@@ -170,11 +175,30 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
170 struct sway_cursor *cursor = wl_container_of(listener, cursor, button); 175 struct sway_cursor *cursor = wl_container_of(listener, cursor, button);
171 struct wlr_event_pointer_button *event = data; 176 struct wlr_event_pointer_button *event = data;
172 177
173 if (event->button == BTN_LEFT) { 178 struct wlr_surface *surface = NULL;
174 struct wlr_surface *surface = NULL; 179 double sx, sy;
175 double sx, sy; 180 struct sway_container *cont =
176 struct sway_container *cont = 181 container_at_cursor(cursor, &surface, &sx, &sy);
177 container_at_cursor(cursor, &surface, &sx, &sy); 182 // Avoid moving keyboard focus from a surface that accepts it to one
183 // that does not unless the change would move us to a new workspace.
184 //
185 // This prevents, for example, losing focus when clicking on swaybar.
186 //
187 // TODO: Replace this condition with something like
188 // !surface_accepts_keyboard_input
189 if (surface && cont && cont->type != C_VIEW) {
190 struct sway_container *new_ws = cont;
191 if (new_ws && new_ws->type != C_WORKSPACE) {
192 new_ws = container_parent(new_ws, C_WORKSPACE);
193 }
194 struct sway_container *old_ws = sway_seat_get_focus(cursor->seat);
195 if (old_ws && old_ws->type != C_WORKSPACE) {
196 old_ws = container_parent(old_ws, C_WORKSPACE);
197 }
198 if (new_ws != old_ws) {
199 sway_seat_set_focus(cursor->seat, cont);
200 }
201 } else {
178 sway_seat_set_focus(cursor->seat, cont); 202 sway_seat_set_focus(cursor->seat, cont);
179 } 203 }
180 204
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
index 99685052..8d22b684 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -97,8 +97,8 @@ static void keyboard_execute_command(struct sway_keyboard *keyboard,
97 config->handler_context.seat = keyboard->seat_device->sway_seat; 97 config->handler_context.seat = keyboard->seat_device->sway_seat;
98 struct cmd_results *results = execute_command(binding->command, NULL); 98 struct cmd_results *results = execute_command(binding->command, NULL);
99 if (results->status != CMD_SUCCESS) { 99 if (results->status != CMD_SUCCESS) {
100 wlr_log(L_DEBUG, "could not run command for binding: %s", 100 wlr_log(L_DEBUG, "could not run command for binding: %s (%s)",
101 binding->command); 101 binding->command, results->error);
102 } 102 }
103 free_cmd_results(results); 103 free_cmd_results(results);
104} 104}
diff --git a/sway/input/seat.c b/sway/input/seat.c
index f969636a..9aa34aca 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -1,5 +1,6 @@
1#define _XOPEN_SOURCE 700 1#define _XOPEN_SOURCE 700
2#include <wlr/types/wlr_cursor.h> 2#include <wlr/types/wlr_cursor.h>
3#include <wlr/types/wlr_output_layout.h>
3#include <wlr/types/wlr_xcursor_manager.h> 4#include <wlr/types/wlr_xcursor_manager.h>
4#include "sway/tree/container.h" 5#include "sway/tree/container.h"
5#include "sway/input/seat.h" 6#include "sway/input/seat.h"
@@ -291,7 +292,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) {
291 seat->cursor->cursor->y); 292 seat->cursor->cursor->y);
292} 293}
293 294
294void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container) { 295void sway_seat_set_focus_warp(struct sway_seat *seat,
296 struct sway_container *container, bool warp) {
295 struct sway_container *last_focus = sway_seat_get_focus(seat); 297 struct sway_container *last_focus = sway_seat_get_focus(seat);
296 298
297 if (container && last_focus == container) { 299 if (container && last_focus == container) {
@@ -311,6 +313,11 @@ void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *containe
311 if (container->type == C_VIEW) { 313 if (container->type == C_VIEW) {
312 struct sway_view *view = container->sway_view; 314 struct sway_view *view = container->sway_view;
313 view_set_activated(view, true); 315 view_set_activated(view, true);
316 if (view->type == SWAY_XWAYLAND_VIEW) {
317 struct wlr_xwayland *xwayland =
318 seat->input->server->xwayland;
319 wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
320 }
314 struct wlr_keyboard *keyboard = 321 struct wlr_keyboard *keyboard =
315 wlr_seat_get_keyboard(seat->wlr_seat); 322 wlr_seat_get_keyboard(seat->wlr_seat);
316 if (keyboard) { 323 if (keyboard) {
@@ -327,15 +334,33 @@ void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *containe
327 if (last_focus) { 334 if (last_focus) {
328 struct sway_container *last_ws = last_focus; 335 struct sway_container *last_ws = last_focus;
329 if (last_ws && last_ws->type != C_WORKSPACE) { 336 if (last_ws && last_ws->type != C_WORKSPACE) {
330 last_ws = container_parent(last_focus, C_WORKSPACE); 337 last_ws = container_parent(last_ws, C_WORKSPACE);
331 } 338 }
332 if (last_ws) { 339 if (last_ws) {
333 wlr_log(L_DEBUG, "sending workspace event");
334 ipc_event_workspace(last_ws, container, "focus"); 340 ipc_event_workspace(last_ws, container, "focus");
335 if (last_ws->children->length == 0) { 341 if (last_ws->children->length == 0) {
336 container_workspace_destroy(last_ws); 342 container_workspace_destroy(last_ws);
337 } 343 }
338 } 344 }
345 struct sway_container *last_output = last_focus;
346 if (last_output && last_output->type != C_OUTPUT) {
347 last_output = container_parent(last_output, C_OUTPUT);
348 }
349 struct sway_container *new_output = container;
350 if (new_output && new_output->type != C_OUTPUT) {
351 new_output = container_parent(new_output, C_OUTPUT);
352 }
353 if (new_output && last_output && new_output != last_output
354 && config->mouse_warping && warp) {
355 struct wlr_output *output = new_output->sway_output->wlr_output;
356 double x = container->x + output->lx + container->width / 2.0;
357 double y = container->y + output->ly + container->height / 2.0;
358 if (!wlr_output_layout_contains_point(
359 root_container.sway_root->output_layout,
360 output, seat->cursor->cursor->x, seat->cursor->cursor->y)) {
361 wlr_cursor_warp(seat->cursor->cursor, NULL, x, y);
362 }
363 }
339 } 364 }
340 365
341 if (last_focus && last_focus->type == C_VIEW && 366 if (last_focus && last_focus->type == C_VIEW &&
@@ -347,6 +372,11 @@ void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *containe
347 seat->has_focus = (container != NULL); 372 seat->has_focus = (container != NULL);
348} 373}
349 374
375void sway_seat_set_focus(struct sway_seat *seat,
376 struct sway_container *container) {
377 sway_seat_set_focus_warp(seat, container, true);
378}
379
350struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { 380struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) {
351 struct sway_seat_container *current = NULL; 381 struct sway_seat_container *current = NULL;
352 struct sway_container *parent = NULL; 382 struct sway_container *parent = NULL;
diff --git a/sway/meson.build b/sway/meson.build
index e8a192f0..38945b4c 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -13,11 +13,13 @@ sway_sources = files(
13 'commands/exec.c', 13 'commands/exec.c',
14 'commands/exec_always.c', 14 'commands/exec_always.c',
15 'commands/focus.c', 15 'commands/focus.c',
16 'commands/focus_follows_mouse.c',
16 'commands/kill.c', 17 'commands/kill.c',
17 'commands/include.c', 18 'commands/include.c',
18 'commands/input.c', 19 'commands/input.c',
19 'commands/layout.c', 20 'commands/layout.c',
20 'commands/mode.c', 21 'commands/mode.c',
22 'commands/move.c',
21 'commands/seat.c', 23 'commands/seat.c',
22 'commands/seat/attach.c', 24 'commands/seat/attach.c',
23 'commands/seat/fallback.c', 25 'commands/seat/fallback.c',
@@ -63,6 +65,7 @@ sway_sources = files(
63 'commands/input/xkb_options.c', 65 'commands/input/xkb_options.c',
64 'commands/input/xkb_rules.c', 66 'commands/input/xkb_rules.c',
65 'commands/input/xkb_variant.c', 67 'commands/input/xkb_variant.c',
68 'commands/mouse_warping.c',
66 'commands/output.c', 69 'commands/output.c',
67 'commands/reload.c', 70 'commands/reload.c',
68 'commands/workspace.c', 71 'commands/workspace.c',
diff --git a/sway/server.c b/sway/server.c
index 9c1671c3..f5cc199c 100644
--- a/sway/server.c
+++ b/sway/server.c
@@ -8,7 +8,9 @@
8#include <wlr/render/wlr_renderer.h> 8#include <wlr/render/wlr_renderer.h>
9#include <wlr/types/wlr_compositor.h> 9#include <wlr/types/wlr_compositor.h>
10#include <wlr/types/wlr_gamma_control.h> 10#include <wlr/types/wlr_gamma_control.h>
11#include <wlr/types/wlr_linux_dmabuf.h>
11#include <wlr/types/wlr_layer_shell.h> 12#include <wlr/types/wlr_layer_shell.h>
13#include <wlr/types/wlr_primary_selection.h>
12#include <wlr/types/wlr_screenshooter.h> 14#include <wlr/types/wlr_screenshooter.h>
13#include <wlr/types/wlr_wl_shell.h> 15#include <wlr/types/wlr_wl_shell.h>
14#include <wlr/types/wlr_xcursor_manager.h> 16#include <wlr/types/wlr_xcursor_manager.h>
@@ -54,6 +56,7 @@ bool server_init(struct sway_server *server) {
54 56
55 wlr_screenshooter_create(server->wl_display); 57 wlr_screenshooter_create(server->wl_display);
56 wlr_gamma_control_manager_create(server->wl_display); 58 wlr_gamma_control_manager_create(server->wl_display);
59 wlr_primary_selection_device_manager_create(server->wl_display);
57 60
58 server->new_output.notify = handle_new_output; 61 server->new_output.notify = handle_new_output;
59 wl_signal_add(&server->backend->events.new_output, &server->new_output); 62 wl_signal_add(&server->backend->events.new_output, &server->new_output);
@@ -68,6 +71,11 @@ bool server_init(struct sway_server *server) {
68 &server->xdg_shell_v6_surface); 71 &server->xdg_shell_v6_surface);
69 server->xdg_shell_v6_surface.notify = handle_xdg_shell_v6_surface; 72 server->xdg_shell_v6_surface.notify = handle_xdg_shell_v6_surface;
70 73
74 server->wl_shell = wlr_wl_shell_create(server->wl_display);
75 wl_signal_add(&server->wl_shell->events.new_surface,
76 &server->wl_shell_surface);
77 server->wl_shell_surface.notify = handle_wl_shell_surface;
78
71 // TODO make xwayland optional 79 // TODO make xwayland optional
72 server->xwayland = 80 server->xwayland =
73 wlr_xwayland_create(server->wl_display, server->compositor); 81 wlr_xwayland_create(server->wl_display, server->compositor);
@@ -91,10 +99,8 @@ bool server_init(struct sway_server *server) {
91 image->hotspot_y); 99 image->hotspot_y);
92 } 100 }
93 101
94 server->wl_shell = wlr_wl_shell_create(server->wl_display); 102 struct wlr_egl *egl = wlr_backend_get_egl(server->backend);
95 wl_signal_add(&server->wl_shell->events.new_surface, 103 wlr_linux_dmabuf_create(server->wl_display, egl);
96 &server->wl_shell_surface);
97 server->wl_shell_surface.notify = handle_wl_shell_surface;
98 104
99 server->socket = wl_display_add_socket_auto(server->wl_display); 105 server->socket = wl_display_add_socket_auto(server->wl_display);
100 if (!server->socket) { 106 if (!server->socket) {
@@ -104,7 +110,6 @@ bool server_init(struct sway_server *server) {
104 } 110 }
105 111
106 input_manager = sway_input_manager_create(server); 112 input_manager = sway_input_manager_create(server);
107
108 return true; 113 return true;
109} 114}
110 115
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 746dbf1f..21fe3fb0 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -33,6 +33,23 @@ static list_t *get_bfs_queue() {
33 return bfs_queue; 33 return bfs_queue;
34} 34}
35 35
36const char *container_type_to_str(enum sway_container_type type) {
37 switch (type) {
38 case C_ROOT:
39 return "C_ROOT";
40 case C_OUTPUT:
41 return "C_OUTPUT";
42 case C_WORKSPACE:
43 return "C_WORKSPACE";
44 case C_CONTAINER:
45 return "C_CONTAINER";
46 case C_VIEW:
47 return "C_VIEW";
48 default:
49 return "C_UNKNOWN";
50 }
51}
52
36static void notify_new_container(struct sway_container *container) { 53static void notify_new_container(struct sway_container *container) {
37 wl_signal_emit(&root_container.sway_root->events.new_container, container); 54 wl_signal_emit(&root_container.sway_root->events.new_container, container);
38 ipc_event_window(container, "new"); 55 ipc_event_window(container, "new");
@@ -54,6 +71,7 @@ static struct sway_container *container_create(enum sway_container_type type) {
54 } 71 }
55 72
56 wl_signal_init(&c->events.destroy); 73 wl_signal_init(&c->events.destroy);
74 wl_signal_init(&c->events.reparent);
57 75
58 return c; 76 return c;
59} 77}
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index 588ceb2d..a8941a40 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -106,8 +106,10 @@ struct sway_container *container_reap_empty(struct sway_container *container) {
106 if (!sway_assert(container, "reaping null container")) { 106 if (!sway_assert(container, "reaping null container")) {
107 return NULL; 107 return NULL;
108 } 108 }
109 wlr_log(L_DEBUG, "reaping %p %s", container, container->name); 109 wlr_log(L_DEBUG, "Reaping %p %s '%s'", container,
110 while (container->children->length == 0) { 110 container_type_to_str(container->type), container->name);
111 while (container->type != C_ROOT && container->type != C_OUTPUT
112 && container->children->length == 0) {
111 if (container->type == C_WORKSPACE) { 113 if (container->type == C_WORKSPACE) {
112 if (!workspace_is_visible(container)) { 114 if (!workspace_is_visible(container)) {
113 struct sway_container *parent = container->parent; 115 struct sway_container *parent = container->parent;
@@ -138,22 +140,46 @@ struct sway_container *container_remove_child(struct sway_container *child) {
138 return container_reap_empty(parent); 140 return container_reap_empty(parent);
139} 141}
140 142
141void container_move_to(struct sway_container* container, 143void container_move_to(struct sway_container *container,
142 struct sway_container* destination) { 144 struct sway_container *destination) {
143 if (container == destination 145 if (container == destination
144 || container_has_anscestor(container, destination)) { 146 || container_has_anscestor(container, destination)) {
145 return; 147 return;
146 } 148 }
147 struct sway_container *old_parent = container_remove_child(container); 149 struct sway_container *old_parent = container_remove_child(container);
148 container->width = container->height = 0; 150 container->width = container->height = 0;
149 struct sway_container *new_parent = 151 struct sway_container *new_parent;
150 container_add_sibling(destination, container); 152 if (destination->type == C_VIEW) {
153 new_parent = container_add_sibling(destination, container);
154 } else {
155 new_parent = destination;
156 container_add_child(destination, container);
157 }
158 wl_signal_emit(&container->events.reparent, old_parent);
159 if (container->type == C_WORKSPACE) {
160 struct sway_seat *seat = sway_input_manager_get_default_seat(
161 input_manager);
162 if (old_parent->children->length == 0) {
163 char *ws_name = workspace_next_name(old_parent->name);
164 struct sway_container *ws =
165 container_workspace_create(old_parent, ws_name);
166 free(ws_name);
167 sway_seat_set_focus(seat, ws);
168 }
169 container_sort_workspaces(new_parent);
170 sway_seat_set_focus(seat, new_parent);
171 }
151 if (old_parent) { 172 if (old_parent) {
152 arrange_windows(old_parent, -1, -1); 173 arrange_windows(old_parent, -1, -1);
153 } 174 }
154 arrange_windows(new_parent, -1, -1); 175 arrange_windows(new_parent, -1, -1);
155} 176}
156 177
178void container_move(struct sway_container *container,
179 enum movement_direction dir, int move_amt) {
180 // TODO
181}
182
157enum sway_container_layout container_get_default_layout( 183enum sway_container_layout container_get_default_layout(
158 struct sway_container *output) { 184 struct sway_container *output) {
159 if (config->default_layout != L_NONE) { 185 if (config->default_layout != L_NONE) {
@@ -521,26 +547,6 @@ static struct sway_container *get_swayc_in_direction_under(
521 } 547 }
522 } 548 }
523 549
524 if (dir == MOVE_PREV || dir == MOVE_NEXT) {
525 int focused_idx = index_child(container);
526 if (focused_idx == -1) {
527 return NULL;
528 } else {
529 int desired = (focused_idx + (dir == MOVE_NEXT ? 1 : -1)) %
530 parent->children->length;
531 if (desired < 0) {
532 desired += parent->children->length;
533 }
534 return parent->children->items[desired];
535 }
536 }
537
538 // If moving to an adjacent output we need a starting position (since this
539 // output might border to multiple outputs).
540 //struct wlc_point abs_pos;
541 //get_layout_center_position(container, &abs_pos);
542
543
544 // TODO WLR fullscreen 550 // TODO WLR fullscreen
545 /* 551 /*
546 if (container->type == C_VIEW && swayc_is_fullscreen(container)) { 552 if (container->type == C_VIEW && swayc_is_fullscreen(container)) {
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 7248fd00..2331dc2b 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -1,3 +1,4 @@
1#include <strings.h>
1#include "sway/tree/container.h" 2#include "sway/tree/container.h"
2#include "sway/tree/layout.h" 3#include "sway/tree/layout.h"
3#include "sway/output.h" 4#include "sway/output.h"
@@ -37,3 +38,13 @@ struct sway_container *container_output_destroy(struct sway_container *output) {
37 container_destroy(output); 38 container_destroy(output);
38 return &root_container; 39 return &root_container;
39} 40}
41
42struct sway_container *output_by_name(const char *name) {
43 for (int i = 0; i < root_container.children->length; ++i) {
44 struct sway_container *output = root_container.children->items[i];
45 if (strcasecmp(output->name, name) == 0){
46 return output;
47 }
48 }
49 return NULL;
50}