diff options
-rw-r--r-- | client/pool-buffer.c | 2 | ||||
-rw-r--r-- | include/sway/config.h | 1 | ||||
-rw-r--r-- | include/sway/input/seat.h | 3 | ||||
-rw-r--r-- | include/sway/output.h | 2 | ||||
-rw-r--r-- | include/sway/tree/container.h | 5 | ||||
-rw-r--r-- | include/sway/tree/layout.h | 12 | ||||
-rw-r--r-- | sway/commands.c | 3 | ||||
-rw-r--r-- | sway/commands/focus.c | 7 | ||||
-rw-r--r-- | sway/commands/focus_follows_mouse.c | 12 | ||||
-rw-r--r-- | sway/commands/mouse_warping.c | 19 | ||||
-rw-r--r-- | sway/commands/move.c | 184 | ||||
-rw-r--r-- | sway/config.c | 1 | ||||
-rw-r--r-- | sway/desktop/layer_shell.c | 5 | ||||
-rw-r--r-- | sway/desktop/output.c | 34 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 18 | ||||
-rw-r--r-- | sway/input/cursor.c | 70 | ||||
-rw-r--r-- | sway/input/keyboard.c | 4 | ||||
-rw-r--r-- | sway/input/seat.c | 36 | ||||
-rw-r--r-- | sway/meson.build | 3 | ||||
-rw-r--r-- | sway/server.c | 15 | ||||
-rw-r--r-- | sway/tree/container.c | 18 | ||||
-rw-r--r-- | sway/tree/layout.c | 58 | ||||
-rw-r--r-- | sway/tree/output.c | 11 |
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 | ||
57 | void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); | 57 | void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); |
58 | 58 | ||
59 | void sway_seat_set_focus_warp(struct sway_seat *seat, | ||
60 | struct sway_container *container, bool warp); | ||
61 | |||
59 | struct sway_container *sway_seat_get_focus(struct sway_seat *seat); | 62 | struct 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); | |||
36 | void output_damage_whole_view(struct sway_output *output, | 36 | void output_damage_whole_view(struct sway_output *output, |
37 | struct sway_view *view); | 37 | struct sway_view *view); |
38 | 38 | ||
39 | struct 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 | ||
93 | const 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? |
91 | struct sway_container *container_output_create( | 96 | struct 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 | ||
19 | struct sway_container; | 16 | struct sway_container; |
@@ -32,7 +29,8 @@ struct sway_root { | |||
32 | 29 | ||
33 | void layout_init(void); | 30 | void layout_init(void); |
34 | 31 | ||
35 | void container_add_child(struct sway_container *parent, struct sway_container *child); | 32 | void container_add_child(struct sway_container *parent, |
33 | struct sway_container *child); | ||
36 | 34 | ||
37 | struct sway_container *container_add_sibling(struct sway_container *parent, | 35 | struct 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); | |||
44 | void container_move_to(struct sway_container* container, | 42 | void container_move_to(struct sway_container* container, |
45 | struct sway_container* destination); | 43 | struct sway_container* destination); |
46 | 44 | ||
47 | enum sway_container_layout container_get_default_layout(struct sway_container *output); | 45 | void container_move(struct sway_container *container, |
46 | enum movement_direction dir, int move_amt); | ||
47 | |||
48 | enum sway_container_layout container_get_default_layout( | ||
49 | struct sway_container *output); | ||
48 | 50 | ||
49 | void container_sort_workspaces(struct sway_container *output); | 51 | void 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 | |||
5 | struct 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 | |||
5 | struct 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 | |||
15 | static 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 | |||
21 | static 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 | |||
49 | static 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 | |||
117 | static 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 | |||
142 | struct 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 | ||
248 | static void handle_map(struct wl_listener *listener, void *data) { | 249 | static 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 | ||
79 | static void set_activated(struct sway_view *view, bool activated) { | 76 | static 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 | ||
157 | static void handle_configure_request(struct wl_listener *listener, void *data) { | 157 | static 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 | ||
159 | static void handle_cursor_motion_absolute(struct wl_listener *listener, | 164 | static 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 | ||
294 | void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container) { | 295 | void 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 | ||
375 | void sway_seat_set_focus(struct sway_seat *seat, | ||
376 | struct sway_container *container) { | ||
377 | sway_seat_set_focus_warp(seat, container, true); | ||
378 | } | ||
379 | |||
350 | struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { | 380 | struct 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 | ||
36 | const 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 | |||
36 | static void notify_new_container(struct sway_container *container) { | 53 | static 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 | ||
141 | void container_move_to(struct sway_container* container, | 143 | void 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 | ||
178 | void container_move(struct sway_container *container, | ||
179 | enum movement_direction dir, int move_amt) { | ||
180 | // TODO | ||
181 | } | ||
182 | |||
157 | enum sway_container_layout container_get_default_layout( | 183 | enum 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 | |||
42 | struct 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 | } | ||