diff options
-rw-r--r-- | include/sway/commands.h | 2 | ||||
-rw-r--r-- | include/sway/output.h | 14 | ||||
-rw-r--r-- | include/sway/server.h | 2 | ||||
-rw-r--r-- | include/sway/tree/container.h | 8 | ||||
-rw-r--r-- | include/sway/tree/layout.h | 5 | ||||
-rw-r--r-- | include/sway/tree/view.h | 10 | ||||
-rw-r--r-- | include/sway/tree/workspace.h | 2 | ||||
-rw-r--r-- | sway/commands.c | 1 | ||||
-rw-r--r-- | sway/commands/default_orientation.c | 21 | ||||
-rw-r--r-- | sway/desktop/layer_shell.c | 26 | ||||
-rw-r--r-- | sway/desktop/output.c | 167 | ||||
-rw-r--r-- | sway/desktop/wl_shell.c | 1 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 52 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 92 | ||||
-rw-r--r-- | sway/input/cursor.c | 99 | ||||
-rw-r--r-- | sway/input/seat.c | 4 | ||||
-rw-r--r-- | sway/ipc-json.c | 69 | ||||
-rw-r--r-- | sway/ipc-server.c | 10 | ||||
-rw-r--r-- | sway/meson.build | 2 | ||||
-rw-r--r-- | sway/server.c | 18 | ||||
-rw-r--r-- | sway/tree/container.c | 78 | ||||
-rw-r--r-- | sway/tree/layout.c | 58 | ||||
-rw-r--r-- | sway/tree/output.c | 39 | ||||
-rw-r--r-- | sway/tree/view.c | 27 | ||||
-rw-r--r-- | sway/tree/workspace.c | 56 | ||||
-rw-r--r-- | swaybg/main.c | 1 |
26 files changed, 576 insertions, 288 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index 1291d5fb..66f097ea 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -95,6 +95,7 @@ sway_cmd cmd_commands; | |||
95 | sway_cmd cmd_debuglog; | 95 | sway_cmd cmd_debuglog; |
96 | sway_cmd cmd_default_border; | 96 | sway_cmd cmd_default_border; |
97 | sway_cmd cmd_default_floating_border; | 97 | sway_cmd cmd_default_floating_border; |
98 | sway_cmd cmd_default_orientation; | ||
98 | sway_cmd cmd_exec; | 99 | sway_cmd cmd_exec; |
99 | sway_cmd cmd_exec_always; | 100 | sway_cmd cmd_exec_always; |
100 | sway_cmd cmd_exit; | 101 | sway_cmd cmd_exit; |
@@ -125,7 +126,6 @@ sway_cmd cmd_move; | |||
125 | sway_cmd cmd_new_float; | 126 | sway_cmd cmd_new_float; |
126 | sway_cmd cmd_new_window; | 127 | sway_cmd cmd_new_window; |
127 | sway_cmd cmd_no_focus; | 128 | sway_cmd cmd_no_focus; |
128 | sway_cmd cmd_orientation; | ||
129 | sway_cmd cmd_output; | 129 | sway_cmd cmd_output; |
130 | sway_cmd cmd_permit; | 130 | sway_cmd cmd_permit; |
131 | sway_cmd cmd_reject; | 131 | sway_cmd cmd_reject; |
diff --git a/include/sway/output.h b/include/sway/output.h index 6fb79987..b4980cd8 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <wayland-server.h> | 5 | #include <wayland-server.h> |
6 | #include <wlr/types/wlr_box.h> | 6 | #include <wlr/types/wlr_box.h> |
7 | #include <wlr/types/wlr_output.h> | 7 | #include <wlr/types/wlr_output.h> |
8 | #include "sway/tree/view.h" | ||
8 | 9 | ||
9 | struct sway_server; | 10 | struct sway_server; |
10 | struct sway_container; | 11 | struct sway_container; |
@@ -13,17 +14,26 @@ struct sway_output { | |||
13 | struct wlr_output *wlr_output; | 14 | struct wlr_output *wlr_output; |
14 | struct sway_container *swayc; | 15 | struct sway_container *swayc; |
15 | struct sway_server *server; | 16 | struct sway_server *server; |
16 | struct timespec last_frame; | ||
17 | 17 | ||
18 | struct wl_list layers[4]; // sway_layer_surface::link | 18 | struct wl_list layers[4]; // sway_layer_surface::link |
19 | struct wlr_box usable_area; | 19 | struct wlr_box usable_area; |
20 | 20 | ||
21 | struct wl_listener frame; | 21 | struct timespec last_frame; |
22 | struct wlr_output_damage *damage; | ||
23 | |||
22 | struct wl_listener destroy; | 24 | struct wl_listener destroy; |
23 | struct wl_listener mode; | 25 | struct wl_listener mode; |
24 | struct wl_listener transform; | 26 | struct wl_listener transform; |
25 | 27 | ||
28 | struct wl_listener damage_destroy; | ||
29 | struct wl_listener damage_frame; | ||
30 | |||
26 | pid_t bg_pid; | 31 | pid_t bg_pid; |
27 | }; | 32 | }; |
28 | 33 | ||
34 | void output_damage_whole(struct sway_output *output); | ||
35 | |||
36 | void output_damage_whole_view(struct sway_output *output, | ||
37 | struct sway_view *view); | ||
38 | |||
29 | #endif | 39 | #endif |
diff --git a/include/sway/server.h b/include/sway/server.h index 25eb64fe..61f21cdb 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -18,7 +18,6 @@ struct sway_server { | |||
18 | const char *socket; | 18 | const char *socket; |
19 | 19 | ||
20 | struct wlr_backend *backend; | 20 | struct wlr_backend *backend; |
21 | struct wlr_renderer *renderer; | ||
22 | 21 | ||
23 | struct wlr_compositor *compositor; | 22 | struct wlr_compositor *compositor; |
24 | struct wlr_data_device_manager *data_device_manager; | 23 | struct wlr_data_device_manager *data_device_manager; |
@@ -26,7 +25,6 @@ struct sway_server { | |||
26 | struct sway_input_manager *input; | 25 | struct sway_input_manager *input; |
27 | 26 | ||
28 | struct wl_listener new_output; | 27 | struct wl_listener new_output; |
29 | struct wl_listener output_frame; | ||
30 | 28 | ||
31 | struct wlr_layer_shell *layer_shell; | 29 | struct wlr_layer_shell *layer_shell; |
32 | struct wl_listener layer_shell_surface; | 30 | struct wl_listener layer_shell_surface; |
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 3bb497db..6aa66da0 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -99,8 +99,13 @@ struct sway_container *container_view_create( | |||
99 | 99 | ||
100 | struct sway_container *container_output_destroy(struct sway_container *output); | 100 | struct sway_container *container_output_destroy(struct sway_container *output); |
101 | 101 | ||
102 | struct sway_container *container_workspace_destroy( | ||
103 | struct sway_container *workspace); | ||
104 | |||
102 | struct sway_container *container_view_destroy(struct sway_container *view); | 105 | struct sway_container *container_view_destroy(struct sway_container *view); |
103 | 106 | ||
107 | struct sway_container *container_destroy(struct sway_container *cont); | ||
108 | |||
104 | struct sway_container *container_set_layout(struct sway_container *container, | 109 | struct sway_container *container_set_layout(struct sway_container *container, |
105 | enum sway_container_layout layout); | 110 | enum sway_container_layout layout); |
106 | 111 | ||
@@ -140,4 +145,7 @@ void container_for_each_descendant_bfs(struct sway_container *container, | |||
140 | void container_for_each_descendant_dfs(struct sway_container *container, | 145 | void container_for_each_descendant_dfs(struct sway_container *container, |
141 | void (*f)(struct sway_container *container, void *data), void *data); | 146 | void (*f)(struct sway_container *container, void *data), void *data); |
142 | 147 | ||
148 | bool container_has_anscestor(struct sway_container *descendant, | ||
149 | struct sway_container *anscestor); | ||
150 | |||
143 | #endif | 151 | #endif |
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index ad52bdb0..0a904c4b 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h | |||
@@ -39,6 +39,11 @@ struct sway_container *container_add_sibling(struct sway_container *parent, | |||
39 | 39 | ||
40 | struct sway_container *container_remove_child(struct sway_container *child); | 40 | struct sway_container *container_remove_child(struct sway_container *child); |
41 | 41 | ||
42 | struct sway_container *container_reap_empty(struct sway_container *container); | ||
43 | |||
44 | void container_move_to(struct sway_container* container, | ||
45 | struct sway_container* destination); | ||
46 | |||
42 | enum sway_container_layout container_get_default_layout(struct sway_container *output); | 47 | enum sway_container_layout container_get_default_layout(struct sway_container *output); |
43 | 48 | ||
44 | void container_sort_workspaces(struct sway_container *output); | 49 | void container_sort_workspaces(struct sway_container *output); |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index e5f53f4e..3965d2b7 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -15,6 +15,8 @@ struct sway_xdg_surface_v6 { | |||
15 | struct wl_listener request_move; | 15 | struct wl_listener request_move; |
16 | struct wl_listener request_resize; | 16 | struct wl_listener request_resize; |
17 | struct wl_listener request_maximize; | 17 | struct wl_listener request_maximize; |
18 | struct wl_listener map; | ||
19 | struct wl_listener unmap; | ||
18 | struct wl_listener destroy; | 20 | struct wl_listener destroy; |
19 | 21 | ||
20 | int pending_width, pending_height; | 22 | int pending_width, pending_height; |
@@ -28,8 +30,8 @@ struct sway_xwayland_surface { | |||
28 | struct wl_listener request_resize; | 30 | struct wl_listener request_resize; |
29 | struct wl_listener request_maximize; | 31 | struct wl_listener request_maximize; |
30 | struct wl_listener request_configure; | 32 | struct wl_listener request_configure; |
31 | struct wl_listener unmap_notify; | 33 | struct wl_listener map; |
32 | struct wl_listener map_notify; | 34 | struct wl_listener unmap; |
33 | struct wl_listener destroy; | 35 | struct wl_listener destroy; |
34 | 36 | ||
35 | int pending_width, pending_height; | 37 | int pending_width, pending_height; |
@@ -113,4 +115,8 @@ void view_close(struct sway_view *view); | |||
113 | 115 | ||
114 | void view_update_outputs(struct sway_view *view, const struct wlr_box *before); | 116 | void view_update_outputs(struct sway_view *view, const struct wlr_box *before); |
115 | 117 | ||
118 | void view_damage_whole(struct sway_view *view); | ||
119 | |||
120 | void view_damage_from(struct sway_view *view); | ||
121 | |||
116 | #endif | 122 | #endif |
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index d73b29c1..4e4c3450 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h | |||
@@ -23,4 +23,6 @@ struct sway_container *workspace_output_prev(struct sway_container *current); | |||
23 | 23 | ||
24 | struct sway_container *workspace_prev(struct sway_container *current); | 24 | struct sway_container *workspace_prev(struct sway_container *current); |
25 | 25 | ||
26 | bool workspace_is_visible(struct sway_container *ws); | ||
27 | |||
26 | #endif | 28 | #endif |
diff --git a/sway/commands.c b/sway/commands.c index bcc777ed..eee7f254 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -149,6 +149,7 @@ static struct cmd_handler bar_colors_handlers[] = { | |||
149 | 149 | ||
150 | /* Config-time only commands. Keep alphabetized */ | 150 | /* Config-time only commands. Keep alphabetized */ |
151 | static struct cmd_handler config_handlers[] = { | 151 | static struct cmd_handler config_handlers[] = { |
152 | { "default_orientation", cmd_default_orientation }, | ||
152 | { "set", cmd_set }, | 153 | { "set", cmd_set }, |
153 | { "swaybg_command", cmd_swaybg_command }, | 154 | { "swaybg_command", cmd_swaybg_command }, |
154 | }; | 155 | }; |
diff --git a/sway/commands/default_orientation.c b/sway/commands/default_orientation.c new file mode 100644 index 00000000..a5347ce2 --- /dev/null +++ b/sway/commands/default_orientation.c | |||
@@ -0,0 +1,21 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | |||
5 | struct cmd_results *cmd_default_orientation(int argc, char **argv) { | ||
6 | struct cmd_results *error = NULL; | ||
7 | if ((error = checkarg(argc, "default_orientation", EXPECTED_EQUAL_TO, 1))) { | ||
8 | return error; | ||
9 | } | ||
10 | if (strcasecmp(argv[0], "horizontal") == 0) { | ||
11 | config->default_orientation = L_HORIZ; | ||
12 | } else if (strcasecmp(argv[0], "vertical") == 0) { | ||
13 | config->default_orientation = L_VERT; | ||
14 | } else if (strcasecmp(argv[0], "auto") == 0) { | ||
15 | // Do nothing | ||
16 | } else { | ||
17 | return cmd_results_new(CMD_INVALID, "default_orientation", | ||
18 | "Expected 'orientation <horizontal|vertical|auto>'"); | ||
19 | } | ||
20 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
21 | } | ||
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index f7e5d19c..5c96659a 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c | |||
@@ -4,12 +4,13 @@ | |||
4 | #include <wayland-server.h> | 4 | #include <wayland-server.h> |
5 | #include <wlr/types/wlr_box.h> | 5 | #include <wlr/types/wlr_box.h> |
6 | #include <wlr/types/wlr_layer_shell.h> | 6 | #include <wlr/types/wlr_layer_shell.h> |
7 | #include <wlr/types/wlr_output_damage.h> | ||
7 | #include <wlr/types/wlr_output.h> | 8 | #include <wlr/types/wlr_output.h> |
8 | #include <wlr/util/log.h> | 9 | #include <wlr/util/log.h> |
9 | #include "sway/layers.h" | 10 | #include "sway/layers.h" |
10 | #include "sway/tree/layout.h" | ||
11 | #include "sway/output.h" | 11 | #include "sway/output.h" |
12 | #include "sway/server.h" | 12 | #include "sway/server.h" |
13 | #include "sway/tree/layout.h" | ||
13 | 14 | ||
14 | static void apply_exclusive(struct wlr_box *usable_area, | 15 | static void apply_exclusive(struct wlr_box *usable_area, |
15 | uint32_t anchor, int32_t exclusive, | 16 | uint32_t anchor, int32_t exclusive, |
@@ -210,20 +211,26 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { | |||
210 | } else { | 211 | } else { |
211 | // TODO DAMAGE from surface damage | 212 | // TODO DAMAGE from surface damage |
212 | } | 213 | } |
214 | wlr_output_damage_add_box(output->damage, &old_geo); | ||
215 | wlr_output_damage_add_box(output->damage, &layer->geo); | ||
213 | } | 216 | } |
214 | } | 217 | } |
215 | 218 | ||
216 | static void unmap(struct wlr_layer_surface *layer_surface) { | 219 | static void unmap(struct sway_layer_surface *sway_layer) { |
217 | // TODO DAMAGE | 220 | struct wlr_output *wlr_output = sway_layer->layer_surface->output; |
221 | if (wlr_output != NULL) { | ||
222 | struct sway_output *output = wlr_output->data; | ||
223 | wlr_output_damage_add_box(output->damage, &sway_layer->geo); | ||
224 | } | ||
218 | } | 225 | } |
219 | 226 | ||
220 | static void handle_destroy(struct wl_listener *listener, void *data) { | 227 | static void handle_destroy(struct wl_listener *listener, void *data) { |
221 | struct sway_layer_surface *sway_layer = wl_container_of( | 228 | struct sway_layer_surface *sway_layer = wl_container_of(listener, |
222 | listener, sway_layer, destroy); | 229 | sway_layer, destroy); |
223 | wlr_log(L_DEBUG, "Layer surface destroyed (%s)", | 230 | wlr_log(L_DEBUG, "Layer surface destroyed (%s)", |
224 | sway_layer->layer_surface->namespace); | 231 | sway_layer->layer_surface->namespace); |
225 | if (sway_layer->layer_surface->mapped) { | 232 | if (sway_layer->layer_surface->mapped) { |
226 | unmap(sway_layer->layer_surface); | 233 | unmap(sway_layer); |
227 | } | 234 | } |
228 | wl_list_remove(&sway_layer->link); | 235 | wl_list_remove(&sway_layer->link); |
229 | wl_list_remove(&sway_layer->destroy.link); | 236 | wl_list_remove(&sway_layer->destroy.link); |
@@ -239,13 +246,16 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
239 | } | 246 | } |
240 | 247 | ||
241 | static void handle_map(struct wl_listener *listener, void *data) { | 248 | static void handle_map(struct wl_listener *listener, void *data) { |
242 | // TODO DAMAGE | 249 | struct sway_layer_surface *sway_layer = wl_container_of(listener, |
250 | sway_layer, map); | ||
251 | struct sway_output *output = sway_layer->layer_surface->output->data; | ||
252 | wlr_output_damage_add_box(output->damage, &sway_layer->geo); | ||
243 | } | 253 | } |
244 | 254 | ||
245 | static void handle_unmap(struct wl_listener *listener, void *data) { | 255 | static void handle_unmap(struct wl_listener *listener, void *data) { |
246 | struct sway_layer_surface *sway_layer = wl_container_of( | 256 | struct sway_layer_surface *sway_layer = wl_container_of( |
247 | listener, sway_layer, unmap); | 257 | listener, sway_layer, unmap); |
248 | unmap(sway_layer->layer_surface); | 258 | unmap(sway_layer); |
249 | } | 259 | } |
250 | 260 | ||
251 | void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | 261 | void handle_layer_shell_surface(struct wl_listener *listener, void *data) { |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 87eb80fe..c248b29e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -6,18 +6,19 @@ | |||
6 | #include <wlr/render/wlr_renderer.h> | 6 | #include <wlr/render/wlr_renderer.h> |
7 | #include <wlr/types/wlr_box.h> | 7 | #include <wlr/types/wlr_box.h> |
8 | #include <wlr/types/wlr_matrix.h> | 8 | #include <wlr/types/wlr_matrix.h> |
9 | #include <wlr/types/wlr_output.h> | 9 | #include <wlr/types/wlr_output_damage.h> |
10 | #include <wlr/types/wlr_output_layout.h> | 10 | #include <wlr/types/wlr_output_layout.h> |
11 | #include <wlr/types/wlr_output.h> | ||
11 | #include <wlr/types/wlr_surface.h> | 12 | #include <wlr/types/wlr_surface.h> |
12 | #include <wlr/types/wlr_wl_shell.h> | 13 | #include <wlr/types/wlr_wl_shell.h> |
13 | #include "log.h" | 14 | #include "log.h" |
14 | #include "sway/tree/container.h" | ||
15 | #include "sway/input/input-manager.h" | 15 | #include "sway/input/input-manager.h" |
16 | #include "sway/input/seat.h" | 16 | #include "sway/input/seat.h" |
17 | #include "sway/layers.h" | 17 | #include "sway/layers.h" |
18 | #include "sway/tree/layout.h" | ||
19 | #include "sway/output.h" | 18 | #include "sway/output.h" |
20 | #include "sway/server.h" | 19 | #include "sway/server.h" |
20 | #include "sway/tree/container.h" | ||
21 | #include "sway/tree/layout.h" | ||
21 | #include "sway/tree/view.h" | 22 | #include "sway/tree/view.h" |
22 | 23 | ||
23 | /** | 24 | /** |
@@ -41,6 +42,9 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, | |||
41 | static void render_surface(struct wlr_surface *surface, | 42 | static void render_surface(struct wlr_surface *surface, |
42 | struct wlr_output *wlr_output, struct timespec *when, | 43 | struct wlr_output *wlr_output, struct timespec *when, |
43 | double lx, double ly, float rotation) { | 44 | double lx, double ly, float rotation) { |
45 | struct wlr_renderer *renderer = | ||
46 | wlr_backend_get_renderer(wlr_output->backend); | ||
47 | |||
44 | if (!wlr_surface_has_buffer(surface)) { | 48 | if (!wlr_surface_has_buffer(surface)) { |
45 | return; | 49 | return; |
46 | } | 50 | } |
@@ -65,8 +69,8 @@ static void render_surface(struct wlr_surface *surface, | |||
65 | float matrix[9]; | 69 | float matrix[9]; |
66 | wlr_matrix_project_box(matrix, &render_box, surface->current->transform, | 70 | wlr_matrix_project_box(matrix, &render_box, surface->current->transform, |
67 | 0, wlr_output->transform_matrix); | 71 | 0, wlr_output->transform_matrix); |
68 | wlr_render_texture_with_matrix(server.renderer, surface->texture, | 72 | wlr_render_texture_with_matrix(renderer, surface->texture, matrix, |
69 | matrix, 1.0f); // TODO: configurable alpha | 73 | 1.0f); // TODO: configurable alpha |
70 | 74 | ||
71 | wlr_surface_send_frame_done(surface, when); | 75 | wlr_surface_send_frame_done(surface, when); |
72 | } | 76 | } |
@@ -142,13 +146,13 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, | |||
142 | 146 | ||
143 | struct render_data { | 147 | struct render_data { |
144 | struct sway_output *output; | 148 | struct sway_output *output; |
145 | struct timespec *now; | 149 | struct timespec *when; |
146 | }; | 150 | }; |
147 | 151 | ||
148 | static void output_frame_view(struct sway_container *view, void *data) { | 152 | static void render_view(struct sway_container *view, void *data) { |
149 | struct render_data *rdata = data; | 153 | struct render_data *rdata = data; |
150 | struct sway_output *output = rdata->output; | 154 | struct sway_output *output = rdata->output; |
151 | struct timespec *now = rdata->now; | 155 | struct timespec *when = rdata->when; |
152 | struct wlr_output *wlr_output = output->wlr_output; | 156 | struct wlr_output *wlr_output = output->wlr_output; |
153 | struct sway_view *sway_view = view->sway_view; | 157 | struct sway_view *sway_view = view->sway_view; |
154 | struct wlr_surface *surface = sway_view->surface; | 158 | struct wlr_surface *surface = sway_view->surface; |
@@ -161,18 +165,18 @@ static void output_frame_view(struct sway_container *view, void *data) { | |||
161 | case SWAY_XDG_SHELL_V6_VIEW: { | 165 | case SWAY_XDG_SHELL_V6_VIEW: { |
162 | int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; | 166 | int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; |
163 | int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; | 167 | int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; |
164 | render_surface(surface, wlr_output, now, | 168 | render_surface(surface, wlr_output, when, |
165 | view->x - window_offset_x, view->y - window_offset_y, 0); | 169 | view->x - window_offset_x, view->y - window_offset_y, 0); |
166 | render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, | 170 | render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, |
167 | now, view->x - window_offset_x, view->y - window_offset_y, 0); | 171 | when, view->x - window_offset_x, view->y - window_offset_y, 0); |
168 | break; | 172 | break; |
169 | } | 173 | } |
170 | case SWAY_WL_SHELL_VIEW: | 174 | case SWAY_WL_SHELL_VIEW: |
171 | render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, | 175 | render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, |
172 | now, view->x, view->y, 0, false); | 176 | when, view->x, view->y, 0, false); |
173 | break; | 177 | break; |
174 | case SWAY_XWAYLAND_VIEW: | 178 | case SWAY_XWAYLAND_VIEW: |
175 | render_surface(surface, wlr_output, now, view->x, view->y, 0); | 179 | render_surface(surface, wlr_output, when, view->x, view->y, 0); |
176 | break; | 180 | break; |
177 | default: | 181 | default: |
178 | break; | 182 | break; |
@@ -192,82 +196,132 @@ static void render_layer(struct sway_output *output, | |||
192 | } | 196 | } |
193 | } | 197 | } |
194 | 198 | ||
195 | static void output_frame_notify(struct wl_listener *listener, void *data) { | 199 | static void render_output(struct sway_output *output, struct timespec *when, |
196 | struct sway_output *soutput = wl_container_of(listener, soutput, frame); | 200 | pixman_region32_t *damage) { |
197 | struct wlr_output *wlr_output = data; | 201 | struct wlr_output *wlr_output = output->wlr_output; |
198 | struct sway_server *server = soutput->server; | 202 | struct wlr_renderer *renderer = |
199 | struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); | 203 | wlr_backend_get_renderer(wlr_output->backend); |
204 | |||
205 | wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); | ||
206 | |||
207 | if (!pixman_region32_not_empty(damage)) { | ||
208 | // Output isn't damaged but needs buffer swap | ||
209 | goto renderer_end; | ||
210 | } | ||
200 | 211 | ||
201 | int buffer_age = -1; | 212 | // TODO: don't damage the whole output here |
202 | wlr_output_make_current(wlr_output, &buffer_age); | 213 | int width, height; |
203 | wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); | 214 | wlr_output_transformed_resolution(wlr_output, &width, &height); |
215 | pixman_region32_union_rect(damage, damage, 0, 0, width, height); | ||
204 | 216 | ||
205 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; | 217 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; |
206 | wlr_renderer_clear(renderer, clear_color); | 218 | wlr_renderer_clear(renderer, clear_color); |
207 | 219 | ||
208 | struct timespec now; | ||
209 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
210 | |||
211 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; | 220 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; |
212 | const struct wlr_box *output_box = wlr_output_layout_get_box( | 221 | const struct wlr_box *output_box = |
213 | layout, wlr_output); | 222 | wlr_output_layout_get_box(layout, wlr_output); |
214 | 223 | ||
215 | render_layer(soutput, output_box, &now, | 224 | render_layer(output, output_box, when, |
216 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | 225 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); |
217 | render_layer(soutput, output_box, &now, | 226 | render_layer(output, output_box, when, |
218 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | 227 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); |
219 | 228 | ||
220 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 229 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
221 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); | 230 | struct sway_container *focus = |
231 | sway_seat_get_focus_inactive(seat, output->swayc); | ||
222 | struct sway_container *workspace = (focus->type == C_WORKSPACE ? | 232 | struct sway_container *workspace = (focus->type == C_WORKSPACE ? |
223 | focus : | 233 | focus : |
224 | container_parent(focus, C_WORKSPACE)); | 234 | container_parent(focus, C_WORKSPACE)); |
225 | 235 | ||
226 | struct render_data rdata = { | 236 | struct render_data rdata = { |
227 | .output = soutput, | 237 | .output = output, |
228 | .now = &now, | 238 | .when = when, |
229 | }; | 239 | }; |
230 | container_descendants(workspace, C_VIEW, output_frame_view, &rdata); | 240 | container_descendants(workspace, C_VIEW, render_view, &rdata); |
231 | 241 | ||
232 | // render unmanaged views on top | 242 | // render unmanaged views on top |
233 | struct sway_view *view; | 243 | struct sway_view *view; |
234 | wl_list_for_each(view, &root_container.sway_root->unmanaged_views, | 244 | wl_list_for_each(view, &root_container.sway_root->unmanaged_views, |
235 | unmanaged_view_link) { | 245 | unmanaged_view_link) { |
236 | if (view->type == SWAY_XWAYLAND_VIEW) { | 246 | if (view->type == SWAY_XWAYLAND_VIEW) { |
237 | // the only kind of unamanged view right now is xwayland override redirect | 247 | // the only kind of unamanged view right now is xwayland override |
248 | // redirect | ||
238 | int view_x = view->wlr_xwayland_surface->x; | 249 | int view_x = view->wlr_xwayland_surface->x; |
239 | int view_y = view->wlr_xwayland_surface->y; | 250 | int view_y = view->wlr_xwayland_surface->y; |
240 | render_surface(view->surface, wlr_output, &soutput->last_frame, | 251 | render_surface(view->surface, wlr_output, &output->last_frame, |
241 | view_x, view_y, 0); | 252 | view_x, view_y, 0); |
242 | } | 253 | } |
243 | } | 254 | } |
244 | 255 | ||
245 | // TODO: Consider revising this when fullscreen windows are supported | 256 | // TODO: Consider revising this when fullscreen windows are supported |
246 | render_layer(soutput, output_box, &now, | 257 | render_layer(output, output_box, when, |
247 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | 258 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); |
248 | render_layer(soutput, output_box, &now, | 259 | render_layer(output, output_box, when, |
249 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | 260 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); |
250 | 261 | ||
251 | wlr_renderer_end(server->renderer); | 262 | renderer_end: |
252 | wlr_output_swap_buffers(wlr_output, &now, NULL); | 263 | wlr_renderer_end(renderer); |
253 | soutput->last_frame = now; | 264 | if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { |
265 | return; | ||
266 | } | ||
267 | output->last_frame = *when; | ||
254 | } | 268 | } |
255 | 269 | ||
256 | static void handle_output_destroy(struct wl_listener *listener, void *data) { | 270 | static void damage_handle_frame(struct wl_listener *listener, void *data) { |
257 | struct sway_output *output = wl_container_of(listener, output, destroy); | 271 | struct sway_output *output = |
258 | struct wlr_output *wlr_output = data; | 272 | wl_container_of(listener, output, damage_frame); |
259 | wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); | 273 | |
274 | if (!output->wlr_output->enabled) { | ||
275 | return; | ||
276 | } | ||
260 | 277 | ||
278 | struct timespec now; | ||
279 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
280 | |||
281 | bool needs_swap; | ||
282 | pixman_region32_t damage; | ||
283 | pixman_region32_init(&damage); | ||
284 | if (!wlr_output_damage_make_current(output->damage, &needs_swap, &damage)) { | ||
285 | return; | ||
286 | } | ||
287 | |||
288 | if (needs_swap) { | ||
289 | render_output(output, &now, &damage); | ||
290 | } | ||
291 | |||
292 | pixman_region32_fini(&damage); | ||
293 | |||
294 | // TODO: send frame done events here instead of inside render_surface | ||
295 | } | ||
296 | |||
297 | void output_damage_whole(struct sway_output *output) { | ||
298 | wlr_output_damage_add_whole(output->damage); | ||
299 | } | ||
300 | |||
301 | void output_damage_whole_view(struct sway_output *output, | ||
302 | struct sway_view *view) { | ||
303 | // TODO | ||
304 | output_damage_whole(output); | ||
305 | } | ||
306 | |||
307 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { | ||
308 | struct sway_output *output = | ||
309 | wl_container_of(listener, output, damage_destroy); | ||
310 | container_output_destroy(output->swayc); | ||
311 | } | ||
312 | |||
313 | static void handle_destroy(struct wl_listener *listener, void *data) { | ||
314 | struct sway_output *output = wl_container_of(listener, output, destroy); | ||
261 | container_output_destroy(output->swayc); | 315 | container_output_destroy(output->swayc); |
262 | } | 316 | } |
263 | 317 | ||
264 | static void handle_output_mode(struct wl_listener *listener, void *data) { | 318 | static void handle_mode(struct wl_listener *listener, void *data) { |
265 | struct sway_output *output = wl_container_of(listener, output, mode); | 319 | struct sway_output *output = wl_container_of(listener, output, mode); |
266 | arrange_layers(output); | 320 | arrange_layers(output); |
267 | arrange_windows(output->swayc, -1, -1); | 321 | arrange_windows(output->swayc, -1, -1); |
268 | } | 322 | } |
269 | 323 | ||
270 | static void handle_output_transform(struct wl_listener *listener, void *data) { | 324 | static void handle_transform(struct wl_listener *listener, void *data) { |
271 | struct sway_output *output = wl_container_of(listener, output, transform); | 325 | struct sway_output *output = wl_container_of(listener, output, transform); |
272 | arrange_layers(output); | 326 | arrange_layers(output); |
273 | arrange_windows(output->swayc, -1, -1); | 327 | arrange_windows(output->swayc, -1, -1); |
@@ -292,6 +346,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
292 | wlr_output_set_mode(wlr_output, mode); | 346 | wlr_output_set_mode(wlr_output, mode); |
293 | } | 347 | } |
294 | 348 | ||
349 | output->damage = wlr_output_damage_create(wlr_output); | ||
350 | |||
295 | output->swayc = container_output_create(output); | 351 | output->swayc = container_output_create(output); |
296 | if (!output->swayc) { | 352 | if (!output->swayc) { |
297 | free(output); | 353 | free(output); |
@@ -305,14 +361,17 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
305 | 361 | ||
306 | sway_input_manager_configure_xcursor(input_manager); | 362 | sway_input_manager_configure_xcursor(input_manager); |
307 | 363 | ||
308 | wl_signal_add(&wlr_output->events.frame, &output->frame); | ||
309 | output->frame.notify = output_frame_notify; | ||
310 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | 364 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); |
311 | output->destroy.notify = handle_output_destroy; | 365 | output->destroy.notify = handle_destroy; |
312 | wl_signal_add(&wlr_output->events.mode, &output->mode); | 366 | wl_signal_add(&wlr_output->events.mode, &output->mode); |
313 | output->mode.notify = handle_output_mode; | 367 | output->mode.notify = handle_mode; |
314 | wl_signal_add(&wlr_output->events.transform, &output->transform); | 368 | wl_signal_add(&wlr_output->events.transform, &output->transform); |
315 | output->transform.notify = handle_output_transform; | 369 | output->transform.notify = handle_transform; |
370 | |||
371 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | ||
372 | output->damage_frame.notify = damage_handle_frame; | ||
373 | wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); | ||
374 | output->damage_destroy.notify = damage_handle_destroy; | ||
316 | 375 | ||
317 | arrange_layers(output); | 376 | arrange_layers(output); |
318 | arrange_windows(&root_container, -1, -1); | 377 | arrange_windows(&root_container, -1, -1); |
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 4d4d1ed7..4fcc6317 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c | |||
@@ -67,6 +67,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
67 | // TODO: Let floating views do whatever | 67 | // TODO: Let floating views do whatever |
68 | view->width = sway_surface->pending_width; | 68 | view->width = sway_surface->pending_width; |
69 | view->height = sway_surface->pending_height; | 69 | view->height = sway_surface->pending_height; |
70 | view_damage_from(view); | ||
70 | } | 71 | } |
71 | 72 | ||
72 | static void handle_destroy(struct wl_listener *listener, void *data) { | 73 | static void handle_destroy(struct wl_listener *listener, void *data) { |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 25c0cbca..713437f2 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -76,6 +76,35 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
76 | // TODO: Let floating views do whatever | 76 | // TODO: Let floating views do whatever |
77 | view->width = sway_surface->pending_width; | 77 | view->width = sway_surface->pending_width; |
78 | view->height = sway_surface->pending_height; | 78 | view->height = sway_surface->pending_height; |
79 | view_damage_from(view); | ||
80 | } | ||
81 | |||
82 | static void handle_unmap(struct wl_listener *listener, void *data) { | ||
83 | struct sway_xdg_surface_v6 *sway_surface = | ||
84 | wl_container_of(listener, sway_surface, unmap); | ||
85 | view_damage_whole(sway_surface->view); | ||
86 | container_view_destroy(sway_surface->view->swayc); | ||
87 | sway_surface->view->swayc = NULL; | ||
88 | sway_surface->view->surface = NULL; | ||
89 | } | ||
90 | |||
91 | static void handle_map(struct wl_listener *listener, void *data) { | ||
92 | struct sway_xdg_surface_v6 *sway_surface = | ||
93 | wl_container_of(listener, sway_surface, map); | ||
94 | struct sway_view *view = sway_surface->view; | ||
95 | |||
96 | sway_surface->view->surface = view->wlr_xdg_surface_v6->surface; | ||
97 | |||
98 | container_view_destroy(view->swayc); | ||
99 | |||
100 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
101 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); | ||
102 | struct sway_container *cont = container_view_create(focus, view); | ||
103 | view->swayc = cont; | ||
104 | arrange_windows(cont->parent, -1, -1); | ||
105 | sway_input_manager_set_focus(input_manager, cont); | ||
106 | |||
107 | view_damage_whole(sway_surface->view); | ||
79 | } | 108 | } |
80 | 109 | ||
81 | static void handle_destroy(struct wl_listener *listener, void *data) { | 110 | static void handle_destroy(struct wl_listener *listener, void *data) { |
@@ -83,10 +112,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
83 | wl_container_of(listener, sway_xdg_surface, destroy); | 112 | wl_container_of(listener, sway_xdg_surface, destroy); |
84 | wl_list_remove(&sway_xdg_surface->commit.link); | 113 | wl_list_remove(&sway_xdg_surface->commit.link); |
85 | wl_list_remove(&sway_xdg_surface->destroy.link); | 114 | wl_list_remove(&sway_xdg_surface->destroy.link); |
86 | struct sway_container *parent = container_view_destroy(sway_xdg_surface->view->swayc); | 115 | container_view_destroy(sway_xdg_surface->view->swayc); |
87 | free(sway_xdg_surface->view); | 116 | free(sway_xdg_surface->view); |
88 | free(sway_xdg_surface); | 117 | free(sway_xdg_surface); |
89 | arrange_windows(parent, -1, -1); | ||
90 | } | 118 | } |
91 | 119 | ||
92 | void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | 120 | void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { |
@@ -122,26 +150,22 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | |||
122 | sway_view->iface.close = close; | 150 | sway_view->iface.close = close; |
123 | sway_view->wlr_xdg_surface_v6 = xdg_surface; | 151 | sway_view->wlr_xdg_surface_v6 = xdg_surface; |
124 | sway_view->sway_xdg_surface_v6 = sway_surface; | 152 | sway_view->sway_xdg_surface_v6 = sway_surface; |
125 | sway_view->surface = xdg_surface->surface; | ||
126 | sway_surface->view = sway_view; | 153 | sway_surface->view = sway_view; |
127 | 154 | ||
128 | // TODO: | 155 | // TODO: |
129 | // - Look up pid and open on appropriate workspace | 156 | // - Look up pid and open on appropriate workspace |
130 | // - Set new view to maximized so it behaves nicely | 157 | // - Set new view to maximized so it behaves nicely |
131 | // - Criteria | 158 | // - Criteria |
132 | 159 | ||
133 | sway_surface->commit.notify = handle_commit; | 160 | sway_surface->commit.notify = handle_commit; |
134 | wl_signal_add(&xdg_surface->surface->events.commit, &sway_surface->commit); | 161 | wl_signal_add(&xdg_surface->surface->events.commit, &sway_surface->commit); |
135 | 162 | ||
136 | sway_surface->destroy.notify = handle_destroy; | 163 | sway_surface->map.notify = handle_map; |
137 | wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); | 164 | wl_signal_add(&xdg_surface->events.map, &sway_surface->map); |
138 | 165 | ||
139 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 166 | sway_surface->unmap.notify = handle_unmap; |
140 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); | 167 | wl_signal_add(&xdg_surface->events.unmap, &sway_surface->unmap); |
141 | struct sway_container *cont = container_view_create(focus, sway_view); | ||
142 | sway_view->swayc = cont; | ||
143 | |||
144 | arrange_windows(cont->parent, -1, -1); | ||
145 | 168 | ||
146 | sway_input_manager_set_focus(input_manager, cont); | 169 | sway_surface->destroy.notify = handle_destroy; |
170 | wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); | ||
147 | } | 171 | } |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 38ee4656..01c993b3 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -14,10 +14,10 @@ | |||
14 | #include "sway/input/input-manager.h" | 14 | #include "sway/input/input-manager.h" |
15 | #include "log.h" | 15 | #include "log.h" |
16 | 16 | ||
17 | static bool assert_xwayland(struct sway_view *view) { | 17 | static bool assert_xwayland(struct sway_view *view) { |
18 | return sway_assert(view->type == SWAY_XWAYLAND_VIEW && view->wlr_xwayland_surface, | 18 | return sway_assert(view->type == SWAY_XWAYLAND_VIEW, |
19 | "Expected xwayland view!"); | 19 | "Expected xwayland view!"); |
20 | } | 20 | } |
21 | 21 | ||
22 | static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | 22 | static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { |
23 | if (!assert_xwayland(view)) { | 23 | if (!assert_xwayland(view)) { |
@@ -99,73 +99,59 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
99 | // TODO: Let floating views do whatever | 99 | // TODO: Let floating views do whatever |
100 | view->width = sway_surface->pending_width; | 100 | view->width = sway_surface->pending_width; |
101 | view->height = sway_surface->pending_height; | 101 | view->height = sway_surface->pending_height; |
102 | view_damage_from(view); | ||
102 | } | 103 | } |
103 | 104 | ||
104 | static void handle_destroy(struct wl_listener *listener, void *data) { | 105 | static void handle_destroy(struct wl_listener *listener, void *data) { |
105 | struct sway_xwayland_surface *sway_surface = | 106 | struct sway_xwayland_surface *sway_surface = |
106 | wl_container_of(listener, sway_surface, destroy); | 107 | wl_container_of(listener, sway_surface, destroy); |
107 | struct wlr_xwayland_surface *xsurface = data; | 108 | |
108 | wl_list_remove(&sway_surface->commit.link); | 109 | wl_list_remove(&sway_surface->commit.link); |
109 | wl_list_remove(&sway_surface->destroy.link); | 110 | wl_list_remove(&sway_surface->destroy.link); |
110 | wl_list_remove(&sway_surface->request_configure.link); | 111 | wl_list_remove(&sway_surface->request_configure.link); |
111 | if (xsurface->override_redirect && xsurface->mapped) { | 112 | wl_list_remove(&sway_surface->view->unmanaged_view_link); |
112 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | 113 | container_view_destroy(sway_surface->view->swayc); |
113 | wl_list_init(&sway_surface->view->unmanaged_view_link); | 114 | sway_surface->view->swayc = NULL; |
114 | } | 115 | sway_surface->view->surface = NULL; |
115 | |||
116 | struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); | ||
117 | if (parent) { | ||
118 | arrange_windows(parent, -1, -1); | ||
119 | } | ||
120 | |||
121 | free(sway_surface->view); | ||
122 | free(sway_surface); | ||
123 | } | 116 | } |
124 | 117 | ||
125 | static void handle_unmap_notify(struct wl_listener *listener, void *data) { | 118 | static void handle_unmap(struct wl_listener *listener, void *data) { |
126 | struct sway_xwayland_surface *sway_surface = | 119 | struct sway_xwayland_surface *sway_surface = |
127 | wl_container_of(listener, sway_surface, unmap_notify); | 120 | wl_container_of(listener, sway_surface, unmap); |
128 | struct wlr_xwayland_surface *xsurface = data; | 121 | view_damage_whole(sway_surface->view); |
129 | if (xsurface->override_redirect && xsurface->mapped) { | 122 | wl_list_remove(&sway_surface->view->unmanaged_view_link); |
130 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | 123 | wl_list_init(&sway_surface->view->unmanaged_view_link); |
131 | wl_list_init(&sway_surface->view->unmanaged_view_link); | 124 | container_view_destroy(sway_surface->view->swayc); |
132 | } | ||
133 | |||
134 | // take it out of the tree | ||
135 | struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); | ||
136 | if (parent) { | ||
137 | arrange_windows(parent, -1, -1); | ||
138 | } | ||
139 | |||
140 | sway_surface->view->swayc = NULL; | 125 | sway_surface->view->swayc = NULL; |
141 | sway_surface->view->surface = NULL; | 126 | sway_surface->view->surface = NULL; |
142 | } | 127 | } |
143 | 128 | ||
144 | static void handle_map_notify(struct wl_listener *listener, void *data) { | 129 | static void handle_map(struct wl_listener *listener, void *data) { |
145 | // TODO put the view back into the tree | ||
146 | struct sway_xwayland_surface *sway_surface = | 130 | struct sway_xwayland_surface *sway_surface = |
147 | wl_container_of(listener, sway_surface, map_notify); | 131 | wl_container_of(listener, sway_surface, map); |
148 | struct wlr_xwayland_surface *xsurface = data; | 132 | struct wlr_xwayland_surface *xsurface = data; |
149 | 133 | ||
150 | sway_surface->view->surface = xsurface->surface; | 134 | sway_surface->view->surface = xsurface->surface; |
151 | 135 | ||
152 | // put it back into the tree | 136 | // put it back into the tree |
153 | if (xsurface->override_redirect) { | 137 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || |
138 | xsurface->override_redirect) { | ||
139 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | ||
154 | wl_list_insert(&root_container.sway_root->unmanaged_views, | 140 | wl_list_insert(&root_container.sway_root->unmanaged_views, |
155 | &sway_surface->view->unmanaged_view_link); | 141 | &sway_surface->view->unmanaged_view_link); |
156 | } else { | 142 | } else { |
157 | struct sway_view *view = sway_surface->view; | 143 | struct sway_view *view = sway_surface->view; |
158 | container_view_destroy(view->swayc); | 144 | container_view_destroy(view->swayc); |
159 | 145 | ||
160 | struct sway_container *parent = root_container.children->items[0]; | 146 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
161 | parent = parent->children->items[0]; // workspace | 147 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); |
162 | 148 | struct sway_container *cont = container_view_create(focus, view); | |
163 | struct sway_container *cont = container_view_create(parent, view); | ||
164 | view->swayc = cont; | 149 | view->swayc = cont; |
165 | |||
166 | arrange_windows(cont->parent, -1, -1); | 150 | arrange_windows(cont->parent, -1, -1); |
167 | sway_input_manager_set_focus(input_manager, cont); | 151 | sway_input_manager_set_focus(input_manager, cont); |
168 | } | 152 | } |
153 | |||
154 | view_damage_whole(sway_surface->view); | ||
169 | } | 155 | } |
170 | 156 | ||
171 | static void handle_configure_request(struct wl_listener *listener, void *data) { | 157 | static void handle_configure_request(struct wl_listener *listener, void *data) { |
@@ -206,9 +192,10 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
206 | sway_view->iface.close = close_view; | 192 | sway_view->iface.close = close_view; |
207 | sway_view->wlr_xwayland_surface = xsurface; | 193 | sway_view->wlr_xwayland_surface = xsurface; |
208 | sway_view->sway_xwayland_surface = sway_surface; | 194 | sway_view->sway_xwayland_surface = sway_surface; |
209 | sway_view->surface = xsurface->surface; | ||
210 | sway_surface->view = sway_view; | 195 | sway_surface->view = sway_view; |
211 | 196 | ||
197 | wl_list_init(&sway_view->unmanaged_view_link); | ||
198 | |||
212 | // TODO: | 199 | // TODO: |
213 | // - Look up pid and open on appropriate workspace | 200 | // - Look up pid and open on appropriate workspace |
214 | // - Set new view to maximized so it behaves nicely | 201 | // - Set new view to maximized so it behaves nicely |
@@ -224,24 +211,11 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
224 | &sway_surface->request_configure); | 211 | &sway_surface->request_configure); |
225 | sway_surface->request_configure.notify = handle_configure_request; | 212 | sway_surface->request_configure.notify = handle_configure_request; |
226 | 213 | ||
227 | wl_signal_add(&xsurface->events.unmap_notify, &sway_surface->unmap_notify); | 214 | wl_signal_add(&xsurface->events.unmap, &sway_surface->unmap); |
228 | sway_surface->unmap_notify.notify = handle_unmap_notify; | 215 | sway_surface->unmap.notify = handle_unmap; |
229 | |||
230 | wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify); | ||
231 | sway_surface->map_notify.notify = handle_map_notify; | ||
232 | |||
233 | if (wlr_xwayland_surface_is_unmanaged(xsurface)) { | ||
234 | // these don't get a container in the tree | ||
235 | wl_list_insert(&root_container.sway_root->unmanaged_views, | ||
236 | &sway_view->unmanaged_view_link); | ||
237 | return; | ||
238 | } | ||
239 | 216 | ||
240 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 217 | wl_signal_add(&xsurface->events.map, &sway_surface->map); |
241 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); | 218 | sway_surface->map.notify = handle_map; |
242 | struct sway_container *cont = container_view_create(focus, sway_view); | ||
243 | sway_view->swayc = cont; | ||
244 | 219 | ||
245 | arrange_windows(cont->parent, -1, -1); | 220 | handle_map(&sway_surface->map, xsurface); |
246 | sway_input_manager_set_focus(input_manager, cont); | ||
247 | } | 221 | } |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index cded0005..d814e08e 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -6,10 +6,11 @@ | |||
6 | #endif | 6 | #endif |
7 | #include <wlr/types/wlr_cursor.h> | 7 | #include <wlr/types/wlr_cursor.h> |
8 | #include <wlr/types/wlr_xcursor_manager.h> | 8 | #include <wlr/types/wlr_xcursor_manager.h> |
9 | #include "sway/input/cursor.h" | ||
10 | #include "sway/tree/view.h" | ||
11 | #include "list.h" | 9 | #include "list.h" |
12 | #include "log.h" | 10 | #include "log.h" |
11 | #include "sway/input/cursor.h" | ||
12 | #include "sway/output.h" | ||
13 | #include "sway/tree/view.h" | ||
13 | 14 | ||
14 | static void cursor_update_position(struct sway_cursor *cursor) { | 15 | static void cursor_update_position(struct sway_cursor *cursor) { |
15 | double x = cursor->cursor->x; | 16 | double x = cursor->cursor->x; |
@@ -19,18 +20,16 @@ static void cursor_update_position(struct sway_cursor *cursor) { | |||
19 | cursor->y = y; | 20 | cursor->y = y; |
20 | } | 21 | } |
21 | 22 | ||
22 | static void cursor_send_pointer_motion(struct sway_cursor *cursor, | 23 | /** |
23 | uint32_t time) { | 24 | * Returns the container at the cursor's position. If the container is a view, |
24 | struct wlr_seat *seat = cursor->seat->wlr_seat; | 25 | * stores the surface at the cursor's position in `*surface`. |
25 | struct wlr_surface *surface = NULL; | 26 | */ |
26 | double sx, sy; | 27 | static struct sway_container *container_at_cursor(struct sway_cursor *cursor, |
27 | 28 | struct wlr_surface **surface, double *sx, double *sy) { | |
28 | struct sway_container *focus = NULL; | ||
29 | |||
30 | // check for unmanaged views first | 29 | // check for unmanaged views first |
30 | struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views; | ||
31 | struct sway_view *view; | 31 | struct sway_view *view; |
32 | wl_list_for_each_reverse(view, &root_container.sway_root->unmanaged_views, | 32 | wl_list_for_each_reverse(view, unmanaged, unmanaged_view_link) { |
33 | unmanaged_view_link) { | ||
34 | if (view->type == SWAY_XWAYLAND_VIEW) { | 33 | if (view->type == SWAY_XWAYLAND_VIEW) { |
35 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | 34 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; |
36 | struct wlr_box box = { | 35 | struct wlr_box box = { |
@@ -41,24 +40,50 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
41 | }; | 40 | }; |
42 | 41 | ||
43 | if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { | 42 | if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { |
44 | focus = view->swayc; | 43 | *surface = xsurface->surface; |
45 | surface = xsurface->surface; | 44 | *sx = cursor->x - box.x; |
46 | sx = cursor->x - box.x; | 45 | *sy = cursor->y - box.y; |
47 | sy = cursor->y - box.y; | 46 | return view->swayc; |
48 | break; | ||
49 | } | 47 | } |
50 | } | 48 | } |
51 | } | 49 | } |
52 | 50 | ||
53 | // then check for managed views | 51 | // find the output the cursor is on |
54 | if (focus == NULL) { | 52 | struct wlr_output_layout *output_layout = |
55 | focus = container_at(&root_container, cursor->x, cursor->y, &surface, | 53 | root_container.sway_root->output_layout; |
56 | &sx, &sy); | 54 | struct wlr_output *wlr_output = |
55 | wlr_output_layout_output_at(output_layout, cursor->x, cursor->y); | ||
56 | if (wlr_output == NULL) { | ||
57 | return NULL; | ||
58 | } | ||
59 | struct sway_output *output = wlr_output->data; | ||
60 | |||
61 | // find the focused workspace on the output for this seat | ||
62 | struct sway_container *workspace_cont = | ||
63 | sway_seat_get_focus_inactive(cursor->seat, output->swayc); | ||
64 | if (workspace_cont != NULL && workspace_cont->type != C_WORKSPACE) { | ||
65 | workspace_cont = container_parent(workspace_cont, C_WORKSPACE); | ||
66 | } | ||
67 | if (workspace_cont == NULL) { | ||
68 | return output->swayc; | ||
57 | } | 69 | } |
58 | 70 | ||
71 | struct sway_container *view_cont = container_at(workspace_cont, | ||
72 | cursor->x, cursor->y, surface, sx, sy); | ||
73 | return view_cont != NULL ? view_cont : workspace_cont; | ||
74 | } | ||
75 | |||
76 | static void cursor_send_pointer_motion(struct sway_cursor *cursor, | ||
77 | uint32_t time) { | ||
78 | struct wlr_seat *seat = cursor->seat->wlr_seat; | ||
79 | struct wlr_surface *surface = NULL; | ||
80 | double sx, sy; | ||
81 | struct sway_container *cont = | ||
82 | container_at_cursor(cursor, &surface, &sx, &sy); | ||
83 | |||
59 | // reset cursor if switching between clients | 84 | // reset cursor if switching between clients |
60 | struct wl_client *client = NULL; | 85 | struct wl_client *client = NULL; |
61 | if (focus) { | 86 | if (surface != NULL) { |
62 | client = wl_resource_get_client(surface->resource); | 87 | client = wl_resource_get_client(surface->resource); |
63 | } | 88 | } |
64 | if (client != cursor->image_client) { | 89 | if (client != cursor->image_client) { |
@@ -68,7 +93,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
68 | } | 93 | } |
69 | 94 | ||
70 | // send pointer enter/leave | 95 | // send pointer enter/leave |
71 | if (focus) { | 96 | if (cont != NULL && surface != NULL) { |
72 | wlr_seat_pointer_notify_enter(seat, surface, sx, sy); | 97 | wlr_seat_pointer_notify_enter(seat, surface, sx, sy); |
73 | wlr_seat_pointer_notify_motion(seat, time, sx, sy); | 98 | wlr_seat_pointer_notify_motion(seat, time, sx, sy); |
74 | } else { | 99 | } else { |
@@ -77,8 +102,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
77 | } | 102 | } |
78 | 103 | ||
79 | static void handle_cursor_motion(struct wl_listener *listener, void *data) { | 104 | static void handle_cursor_motion(struct wl_listener *listener, void *data) { |
80 | struct sway_cursor *cursor = | 105 | struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); |
81 | wl_container_of(listener, cursor, motion); | ||
82 | struct wlr_event_pointer_motion *event = data; | 106 | struct wlr_event_pointer_motion *event = data; |
83 | wlr_cursor_move(cursor->cursor, event->device, | 107 | wlr_cursor_move(cursor->cursor, event->device, |
84 | event->delta_x, event->delta_y); | 108 | event->delta_x, event->delta_y); |
@@ -97,17 +121,15 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener, | |||
97 | } | 121 | } |
98 | 122 | ||
99 | static void handle_cursor_button(struct wl_listener *listener, void *data) { | 123 | static void handle_cursor_button(struct wl_listener *listener, void *data) { |
100 | struct sway_cursor *cursor = | 124 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); |
101 | wl_container_of(listener, cursor, button); | ||
102 | struct wlr_event_pointer_button *event = data; | 125 | struct wlr_event_pointer_button *event = data; |
103 | 126 | ||
104 | if (event->button == BTN_LEFT) { | 127 | if (event->button == BTN_LEFT) { |
105 | struct wlr_surface *surface = NULL; | 128 | struct wlr_surface *surface = NULL; |
106 | double sx, sy; | 129 | double sx, sy; |
107 | struct sway_container *swayc = | 130 | struct sway_container *cont = |
108 | container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); | 131 | container_at_cursor(cursor, &surface, &sx, &sy); |
109 | 132 | sway_seat_set_focus(cursor->seat, cont); | |
110 | sway_seat_set_focus(cursor->seat, swayc); | ||
111 | } | 133 | } |
112 | 134 | ||
113 | wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, | 135 | wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, |
@@ -115,23 +137,20 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { | |||
115 | } | 137 | } |
116 | 138 | ||
117 | static void handle_cursor_axis(struct wl_listener *listener, void *data) { | 139 | static void handle_cursor_axis(struct wl_listener *listener, void *data) { |
118 | struct sway_cursor *cursor = | 140 | struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); |
119 | wl_container_of(listener, cursor, axis); | ||
120 | struct wlr_event_pointer_axis *event = data; | 141 | struct wlr_event_pointer_axis *event = data; |
121 | wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, | 142 | wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, |
122 | event->orientation, event->delta); | 143 | event->orientation, event->delta); |
123 | } | 144 | } |
124 | 145 | ||
125 | static void handle_touch_down(struct wl_listener *listener, void *data) { | 146 | static void handle_touch_down(struct wl_listener *listener, void *data) { |
126 | struct sway_cursor *cursor = | 147 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); |
127 | wl_container_of(listener, cursor, touch_down); | ||
128 | struct wlr_event_touch_down *event = data; | 148 | struct wlr_event_touch_down *event = data; |
129 | wlr_log(L_DEBUG, "TODO: handle touch down event: %p", event); | 149 | wlr_log(L_DEBUG, "TODO: handle touch down event: %p", event); |
130 | } | 150 | } |
131 | 151 | ||
132 | static void handle_touch_up(struct wl_listener *listener, void *data) { | 152 | static void handle_touch_up(struct wl_listener *listener, void *data) { |
133 | struct sway_cursor *cursor = | 153 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); |
134 | wl_container_of(listener, cursor, touch_up); | ||
135 | struct wlr_event_touch_up *event = data; | 154 | struct wlr_event_touch_up *event = data; |
136 | wlr_log(L_DEBUG, "TODO: handle touch up event: %p", event); | 155 | wlr_log(L_DEBUG, "TODO: handle touch up event: %p", event); |
137 | } | 156 | } |
@@ -144,15 +163,13 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { | |||
144 | } | 163 | } |
145 | 164 | ||
146 | static void handle_tool_axis(struct wl_listener *listener, void *data) { | 165 | static void handle_tool_axis(struct wl_listener *listener, void *data) { |
147 | struct sway_cursor *cursor = | 166 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); |
148 | wl_container_of(listener, cursor, tool_axis); | ||
149 | struct wlr_event_tablet_tool_axis *event = data; | 167 | struct wlr_event_tablet_tool_axis *event = data; |
150 | wlr_log(L_DEBUG, "TODO: handle tool axis event: %p", event); | 168 | wlr_log(L_DEBUG, "TODO: handle tool axis event: %p", event); |
151 | } | 169 | } |
152 | 170 | ||
153 | static void handle_tool_tip(struct wl_listener *listener, void *data) { | 171 | static void handle_tool_tip(struct wl_listener *listener, void *data) { |
154 | struct sway_cursor *cursor = | 172 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); |
155 | wl_container_of(listener, cursor, tool_tip); | ||
156 | struct wlr_event_tablet_tool_tip *event = data; | 173 | struct wlr_event_tablet_tool_tip *event = data; |
157 | wlr_log(L_DEBUG, "TODO: handle tool tip event: %p", event); | 174 | wlr_log(L_DEBUG, "TODO: handle tool tip event: %p", event); |
158 | } | 175 | } |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 7cf0dd08..ae536264 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include "sway/input/keyboard.h" | 8 | #include "sway/input/keyboard.h" |
9 | #include "sway/ipc-server.h" | 9 | #include "sway/ipc-server.h" |
10 | #include "sway/output.h" | 10 | #include "sway/output.h" |
11 | #include "sway/tree/container.h" | ||
11 | #include "sway/tree/view.h" | 12 | #include "sway/tree/view.h" |
12 | #include "log.h" | 13 | #include "log.h" |
13 | 14 | ||
@@ -331,6 +332,9 @@ void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *containe | |||
331 | if (last_ws) { | 332 | if (last_ws) { |
332 | wlr_log(L_DEBUG, "sending workspace event"); | 333 | wlr_log(L_DEBUG, "sending workspace event"); |
333 | ipc_event_workspace(last_ws, container, "focus"); | 334 | ipc_event_workspace(last_ws, container, "focus"); |
335 | if (last_ws->children->length == 0) { | ||
336 | container_workspace_destroy(last_ws); | ||
337 | } | ||
334 | } | 338 | } |
335 | } | 339 | } |
336 | 340 | ||
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index eab6399f..7c5f7304 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -66,19 +66,42 @@ static const char *ipc_json_get_output_transform(enum wl_output_transform transf | |||
66 | 66 | ||
67 | static void ipc_json_describe_output(struct sway_container *container, json_object *object) { | 67 | static void ipc_json_describe_output(struct sway_container *container, json_object *object) { |
68 | struct wlr_output *wlr_output = container->sway_output->wlr_output; | 68 | struct wlr_output *wlr_output = container->sway_output->wlr_output; |
69 | json_object_object_add(object, "type", json_object_new_string("output")); | 69 | json_object_object_add(object, "type", |
70 | json_object_object_add(object, "active", json_object_new_boolean(true)); | 70 | json_object_new_string("output")); |
71 | json_object_object_add(object, "primary", json_object_new_boolean(false)); | 71 | json_object_object_add(object, "active", |
72 | json_object_object_add(object, "layout", json_object_new_string("output")); | 72 | json_object_new_boolean(true)); |
73 | json_object_object_add(object, "make", json_object_new_string(wlr_output->make)); | 73 | json_object_object_add(object, "primary", |
74 | json_object_object_add(object, "model", json_object_new_string(wlr_output->model)); | 74 | json_object_new_boolean(false)); |
75 | json_object_object_add(object, "serial", json_object_new_string(wlr_output->serial)); | 75 | json_object_object_add(object, "layout", |
76 | json_object_object_add(object, "scale", json_object_new_double(wlr_output->scale)); | 76 | json_object_new_string("output")); |
77 | json_object_object_add(object, "refresh", json_object_new_int(wlr_output->refresh)); | 77 | json_object_object_add(object, "make", |
78 | json_object_new_string(wlr_output->make)); | ||
79 | json_object_object_add(object, "model", | ||
80 | json_object_new_string(wlr_output->model)); | ||
81 | json_object_object_add(object, "serial", | ||
82 | json_object_new_string(wlr_output->serial)); | ||
83 | json_object_object_add(object, "scale", | ||
84 | json_object_new_double(wlr_output->scale)); | ||
85 | json_object_object_add(object, "refresh", | ||
86 | json_object_new_int(wlr_output->refresh)); | ||
78 | json_object_object_add(object, "transform", | 87 | json_object_object_add(object, "transform", |
79 | json_object_new_string(ipc_json_get_output_transform(wlr_output->transform))); | 88 | json_object_new_string( |
80 | // TODO WLR need to set "current_workspace" to the currently focused | 89 | ipc_json_get_output_transform(wlr_output->transform))); |
81 | // workspace in a way that makes sense with multiseat | 90 | |
91 | struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); | ||
92 | const char *ws = NULL; | ||
93 | if (seat) { | ||
94 | struct sway_container *focus = | ||
95 | sway_seat_get_focus_inactive(seat, container); | ||
96 | if (focus && focus->type != C_WORKSPACE) { | ||
97 | focus = container_parent(focus, C_WORKSPACE); | ||
98 | } | ||
99 | if (focus) { | ||
100 | ws = focus->name; | ||
101 | } | ||
102 | } | ||
103 | json_object_object_add(object, "current_workspace", | ||
104 | json_object_new_string(ws)); | ||
82 | 105 | ||
83 | json_object *modes_array = json_object_new_array(); | 106 | json_object *modes_array = json_object_new_array(); |
84 | struct wlr_output_mode *mode; | 107 | struct wlr_output_mode *mode; |
@@ -95,16 +118,20 @@ static void ipc_json_describe_output(struct sway_container *container, json_obje | |||
95 | json_object_object_add(object, "modes", modes_array); | 118 | json_object_object_add(object, "modes", modes_array); |
96 | } | 119 | } |
97 | 120 | ||
98 | static void ipc_json_describe_workspace(struct sway_container *workspace, json_object *object) { | 121 | static void ipc_json_describe_workspace(struct sway_container *workspace, |
99 | int num = (isdigit(workspace->name[0])) ? atoi(workspace->name) : -1; | 122 | json_object *object) { |
123 | int num = isdigit(workspace->name[0]) ? atoi(workspace->name) : -1; | ||
100 | 124 | ||
101 | json_object_object_add(object, "num", json_object_new_int(num)); | 125 | json_object_object_add(object, "num", json_object_new_int(num)); |
102 | json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL); | 126 | json_object_object_add(object, "output", workspace->parent ? |
127 | json_object_new_string(workspace->parent->name) : NULL); | ||
103 | json_object_object_add(object, "type", json_object_new_string("workspace")); | 128 | json_object_object_add(object, "type", json_object_new_string("workspace")); |
129 | json_object_object_add(object, "urgent", json_object_new_boolean(false)); | ||
104 | } | 130 | } |
105 | 131 | ||
106 | static void ipc_json_describe_view(struct sway_container *c, json_object *object) { | 132 | static void ipc_json_describe_view(struct sway_container *c, json_object *object) { |
107 | json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); | 133 | json_object_object_add(object, "name", |
134 | c->name ? json_object_new_string(c->name) : NULL); | ||
108 | } | 135 | } |
109 | 136 | ||
110 | json_object *ipc_json_describe_container(struct sway_container *c) { | 137 | json_object *ipc_json_describe_container(struct sway_container *c) { |
@@ -118,28 +145,26 @@ json_object *ipc_json_describe_container(struct sway_container *c) { | |||
118 | json_object *object = json_object_new_object(); | 145 | json_object *object = json_object_new_object(); |
119 | 146 | ||
120 | json_object_object_add(object, "id", json_object_new_int((int)c->id)); | 147 | json_object_object_add(object, "id", json_object_new_int((int)c->id)); |
121 | json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); | 148 | json_object_object_add(object, "name", |
149 | c->name ? json_object_new_string(c->name) : NULL); | ||
122 | json_object_object_add(object, "rect", ipc_json_create_rect(c)); | 150 | json_object_object_add(object, "rect", ipc_json_create_rect(c)); |
123 | json_object_object_add(object, "focused", json_object_new_boolean(focused)); | 151 | json_object_object_add(object, "focused", |
152 | json_object_new_boolean(focused)); | ||
124 | 153 | ||
125 | switch (c->type) { | 154 | switch (c->type) { |
126 | case C_ROOT: | 155 | case C_ROOT: |
127 | ipc_json_describe_root(c, object); | 156 | ipc_json_describe_root(c, object); |
128 | break; | 157 | break; |
129 | |||
130 | case C_OUTPUT: | 158 | case C_OUTPUT: |
131 | ipc_json_describe_output(c, object); | 159 | ipc_json_describe_output(c, object); |
132 | break; | 160 | break; |
133 | |||
134 | case C_CONTAINER: | 161 | case C_CONTAINER: |
135 | case C_VIEW: | 162 | case C_VIEW: |
136 | ipc_json_describe_view(c, object); | 163 | ipc_json_describe_view(c, object); |
137 | break; | 164 | break; |
138 | |||
139 | case C_WORKSPACE: | 165 | case C_WORKSPACE: |
140 | ipc_json_describe_workspace(c, object); | 166 | ipc_json_describe_workspace(c, object); |
141 | break; | 167 | break; |
142 | |||
143 | case C_TYPES: | 168 | case C_TYPES: |
144 | default: | 169 | default: |
145 | break; | 170 | break; |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 394161af..869f1ed0 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -390,7 +390,7 @@ static void ipc_get_workspaces_callback(struct sway_container *workspace, | |||
390 | struct sway_seat *seat = | 390 | struct sway_seat *seat = |
391 | sway_input_manager_get_default_seat(input_manager); | 391 | sway_input_manager_get_default_seat(input_manager); |
392 | struct sway_container *focused_ws = sway_seat_get_focus(seat); | 392 | struct sway_container *focused_ws = sway_seat_get_focus(seat); |
393 | if (focused_ws->type != C_WORKSPACE) { | 393 | if (focused_ws != NULL && focused_ws->type != C_WORKSPACE) { |
394 | focused_ws = container_parent(focused_ws, C_WORKSPACE); | 394 | focused_ws = container_parent(focused_ws, C_WORKSPACE); |
395 | } | 395 | } |
396 | bool focused = workspace == focused_ws; | 396 | bool focused = workspace == focused_ws; |
@@ -398,6 +398,14 @@ static void ipc_get_workspaces_callback(struct sway_container *workspace, | |||
398 | json_object_object_add(workspace_json, "focused", | 398 | json_object_object_add(workspace_json, "focused", |
399 | json_object_new_boolean(focused)); | 399 | json_object_new_boolean(focused)); |
400 | json_object_array_add((json_object *)data, workspace_json); | 400 | json_object_array_add((json_object *)data, workspace_json); |
401 | |||
402 | focused_ws = sway_seat_get_focus_inactive(seat, workspace->parent); | ||
403 | if (focused_ws->type != C_WORKSPACE) { | ||
404 | focused_ws = container_parent(focused_ws, C_WORKSPACE); | ||
405 | } | ||
406 | bool visible = workspace == focused_ws; | ||
407 | json_object_object_add(workspace_json, "visible", | ||
408 | json_object_new_boolean(visible)); | ||
401 | } | 409 | } |
402 | 410 | ||
403 | void ipc_client_handle_command(struct ipc_client *client) { | 411 | void ipc_client_handle_command(struct ipc_client *client) { |
diff --git a/sway/meson.build b/sway/meson.build index 1e7ee7ae..e8a192f0 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -8,6 +8,7 @@ sway_sources = files( | |||
8 | 'input/keyboard.c', | 8 | 'input/keyboard.c', |
9 | 'commands/bar.c', | 9 | 'commands/bar.c', |
10 | 'commands/bind.c', | 10 | 'commands/bind.c', |
11 | 'commands/default_orientation.c', | ||
11 | 'commands/exit.c', | 12 | 'commands/exit.c', |
12 | 'commands/exec.c', | 13 | 'commands/exec.c', |
13 | 'commands/exec_always.c', | 14 | 'commands/exec_always.c', |
@@ -81,6 +82,7 @@ sway_sources = files( | |||
81 | 'security.c', | 82 | 'security.c', |
82 | 'tree/container.c', | 83 | 'tree/container.c', |
83 | 'tree/layout.c', | 84 | 'tree/layout.c', |
85 | 'tree/output.c', | ||
84 | 'tree/view.c', | 86 | 'tree/view.c', |
85 | 'tree/workspace.c', | 87 | 'tree/workspace.c', |
86 | ) | 88 | ) |
diff --git a/sway/server.c b/sway/server.c index 3fba019d..728e624e 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -1,19 +1,19 @@ | |||
1 | #define _POSIX_C_SOURCE 200112L | 1 | #define _POSIX_C_SOURCE 200112L |
2 | #include <stdlib.h> | 2 | #include <assert.h> |
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include <stdlib.h> | ||
4 | #include <wayland-server.h> | 5 | #include <wayland-server.h> |
5 | #include <wlr/backend.h> | 6 | #include <wlr/backend.h> |
6 | #include <wlr/backend/session.h> | 7 | #include <wlr/backend/session.h> |
7 | #include <wlr/render/wlr_renderer.h> | 8 | #include <wlr/render/wlr_renderer.h> |
8 | #include <wlr/render/gles2.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_layer_shell.h> | 11 | #include <wlr/types/wlr_layer_shell.h> |
11 | #include <wlr/types/wlr_screenshooter.h> | 12 | #include <wlr/types/wlr_screenshooter.h> |
12 | #include <wlr/types/wlr_gamma_control.h> | ||
13 | #include <wlr/types/wlr_wl_shell.h> | 13 | #include <wlr/types/wlr_wl_shell.h> |
14 | #include <wlr/util/log.h> | ||
14 | // TODO WLR: make Xwayland optional | 15 | // TODO WLR: make Xwayland optional |
15 | #include <wlr/xwayland.h> | 16 | #include <wlr/xwayland.h> |
16 | #include <wlr/util/log.h> | ||
17 | #include "sway/commands.h" | 17 | #include "sway/commands.h" |
18 | #include "sway/config.h" | 18 | #include "sway/config.h" |
19 | #include "sway/server.h" | 19 | #include "sway/server.h" |
@@ -42,11 +42,12 @@ bool server_init(struct sway_server *server) { | |||
42 | server->wl_event_loop = wl_display_get_event_loop(server->wl_display); | 42 | server->wl_event_loop = wl_display_get_event_loop(server->wl_display); |
43 | server->backend = wlr_backend_autocreate(server->wl_display); | 43 | server->backend = wlr_backend_autocreate(server->wl_display); |
44 | 44 | ||
45 | server->renderer = wlr_gles2_renderer_create(server->backend); | 45 | struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend); |
46 | assert(renderer); | ||
47 | |||
46 | wl_display_init_shm(server->wl_display); | 48 | wl_display_init_shm(server->wl_display); |
47 | 49 | ||
48 | server->compositor = wlr_compositor_create( | 50 | server->compositor = wlr_compositor_create(server->wl_display, renderer); |
49 | server->wl_display, server->renderer); | ||
50 | server->data_device_manager = | 51 | server->data_device_manager = |
51 | wlr_data_device_manager_create(server->wl_display); | 52 | wlr_data_device_manager_create(server->wl_display); |
52 | 53 | ||
@@ -95,8 +96,7 @@ bool server_init(struct sway_server *server) { | |||
95 | } | 96 | } |
96 | 97 | ||
97 | void server_fini(struct sway_server *server) { | 98 | void server_fini(struct sway_server *server) { |
98 | // TODO WLR: tear down more stuff | 99 | // TODO |
99 | wlr_backend_destroy(server->backend); | ||
100 | } | 100 | } |
101 | 101 | ||
102 | void server_run(struct sway_server *server) { | 102 | void server_run(struct sway_server *server) { |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 2eac812e..8705edc7 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -6,16 +6,16 @@ | |||
6 | #include <wayland-server.h> | 6 | #include <wayland-server.h> |
7 | #include <wlr/types/wlr_output_layout.h> | 7 | #include <wlr/types/wlr_output_layout.h> |
8 | #include <wlr/types/wlr_wl_shell.h> | 8 | #include <wlr/types/wlr_wl_shell.h> |
9 | #include "log.h" | ||
9 | #include "sway/config.h" | 10 | #include "sway/config.h" |
10 | #include "sway/tree/container.h" | ||
11 | #include "sway/input/input-manager.h" | 11 | #include "sway/input/input-manager.h" |
12 | #include "sway/input/seat.h" | 12 | #include "sway/input/seat.h" |
13 | #include "sway/tree/layout.h" | 13 | #include "sway/ipc-server.h" |
14 | #include "sway/output.h" | 14 | #include "sway/output.h" |
15 | #include "sway/server.h" | 15 | #include "sway/server.h" |
16 | #include "sway/tree/layout.h" | ||
16 | #include "sway/tree/view.h" | 17 | #include "sway/tree/view.h" |
17 | #include "sway/tree/workspace.h" | 18 | #include "sway/tree/workspace.h" |
18 | #include "sway/ipc-server.h" | ||
19 | #include "log.h" | 19 | #include "log.h" |
20 | 20 | ||
21 | static list_t *bfs_queue; | 21 | static list_t *bfs_queue; |
@@ -58,13 +58,14 @@ static struct sway_container *container_create(enum sway_container_type type) { | |||
58 | return c; | 58 | return c; |
59 | } | 59 | } |
60 | 60 | ||
61 | static void container_destroy(struct sway_container *cont) { | 61 | struct sway_container *container_destroy(struct sway_container *cont) { |
62 | if (cont == NULL) { | 62 | if (cont == NULL) { |
63 | return; | 63 | return NULL; |
64 | } | 64 | } |
65 | 65 | ||
66 | wl_signal_emit(&cont->events.destroy, cont); | 66 | wl_signal_emit(&cont->events.destroy, cont); |
67 | 67 | ||
68 | struct sway_container *parent = cont->parent; | ||
68 | if (cont->children) { | 69 | if (cont->children) { |
69 | // remove children until there are no more, container_destroy calls | 70 | // remove children until there are no more, container_destroy calls |
70 | // container_remove_child, which removes child from this container | 71 | // container_remove_child, which removes child from this container |
@@ -77,13 +78,14 @@ static void container_destroy(struct sway_container *cont) { | |||
77 | list_foreach(cont->marks, free); | 78 | list_foreach(cont->marks, free); |
78 | list_free(cont->marks); | 79 | list_free(cont->marks); |
79 | } | 80 | } |
80 | if (cont->parent) { | 81 | if (parent) { |
81 | container_remove_child(cont); | 82 | parent = container_remove_child(cont); |
82 | } | 83 | } |
83 | if (cont->name) { | 84 | if (cont->name) { |
84 | free(cont->name); | 85 | free(cont->name); |
85 | } | 86 | } |
86 | free(cont); | 87 | free(cont); |
88 | return parent; | ||
87 | } | 89 | } |
88 | 90 | ||
89 | struct sway_container *container_output_create( | 91 | struct sway_container *container_output_create( |
@@ -202,57 +204,6 @@ struct sway_container *container_view_create(struct sway_container *sibling, | |||
202 | return swayc; | 204 | return swayc; |
203 | } | 205 | } |
204 | 206 | ||
205 | struct sway_container *container_output_destroy(struct sway_container *output) { | ||
206 | if (!sway_assert(output, | ||
207 | "null output passed to container_output_destroy")) { | ||
208 | return NULL; | ||
209 | } | ||
210 | |||
211 | if (output->children->length > 0) { | ||
212 | // TODO save workspaces when there are no outputs. | ||
213 | // TODO also check if there will ever be no outputs except for exiting | ||
214 | // program | ||
215 | if (root_container.children->length > 1) { | ||
216 | int p = root_container.children->items[0] == output; | ||
217 | // Move workspace from this output to another output | ||
218 | while (output->children->length) { | ||
219 | struct sway_container *child = output->children->items[0]; | ||
220 | container_remove_child(child); | ||
221 | container_add_child(root_container.children->items[p], child); | ||
222 | } | ||
223 | container_sort_workspaces(root_container.children->items[p]); | ||
224 | arrange_windows(root_container.children->items[p], | ||
225 | -1, -1); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | wl_list_remove(&output->sway_output->frame.link); | ||
230 | wl_list_remove(&output->sway_output->destroy.link); | ||
231 | wl_list_remove(&output->sway_output->mode.link); | ||
232 | |||
233 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); | ||
234 | container_destroy(output); | ||
235 | |||
236 | return &root_container; | ||
237 | } | ||
238 | |||
239 | struct sway_container *container_view_destroy(struct sway_container *view) { | ||
240 | if (!view) { | ||
241 | return NULL; | ||
242 | } | ||
243 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); | ||
244 | struct sway_container *parent = view->parent; | ||
245 | container_destroy(view); | ||
246 | |||
247 | // TODO WLR: Destroy empty containers | ||
248 | /* | ||
249 | if (parent && parent->type == C_CONTAINER) { | ||
250 | return destroy_container(parent); | ||
251 | } | ||
252 | */ | ||
253 | return parent; | ||
254 | } | ||
255 | |||
256 | struct sway_container *container_set_layout(struct sway_container *container, | 207 | struct sway_container *container_set_layout(struct sway_container *container, |
257 | enum sway_container_layout layout) { | 208 | enum sway_container_layout layout) { |
258 | if (container->type == C_WORKSPACE) { | 209 | if (container->type == C_WORKSPACE) { |
@@ -438,3 +389,14 @@ void container_for_each_descendant_bfs(struct sway_container *con, | |||
438 | list_cat(queue, current->children); | 389 | list_cat(queue, current->children); |
439 | } | 390 | } |
440 | } | 391 | } |
392 | |||
393 | bool container_has_anscestor(struct sway_container *descendant, | ||
394 | struct sway_container *anscestor) { | ||
395 | while (descendant->type != C_ROOT) { | ||
396 | descendant = descendant->parent; | ||
397 | if (descendant == anscestor) { | ||
398 | return true; | ||
399 | } | ||
400 | } | ||
401 | return false; | ||
402 | } | ||
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index dc0ee5b4..588ceb2d 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -9,8 +9,10 @@ | |||
9 | #include "sway/tree/container.h" | 9 | #include "sway/tree/container.h" |
10 | #include "sway/tree/layout.h" | 10 | #include "sway/tree/layout.h" |
11 | #include "sway/output.h" | 11 | #include "sway/output.h" |
12 | #include "sway/tree/workspace.h" | ||
12 | #include "sway/tree/view.h" | 13 | #include "sway/tree/view.h" |
13 | #include "sway/input/seat.h" | 14 | #include "sway/input/seat.h" |
15 | #include "sway/ipc-server.h" | ||
14 | #include "list.h" | 16 | #include "list.h" |
15 | #include "log.h" | 17 | #include "log.h" |
16 | 18 | ||
@@ -98,37 +100,67 @@ void container_add_child(struct sway_container *parent, | |||
98 | parent, parent->type, parent->width, parent->height); | 100 | parent, parent->type, parent->width, parent->height); |
99 | list_add(parent->children, child); | 101 | list_add(parent->children, child); |
100 | child->parent = parent; | 102 | child->parent = parent; |
101 | // set focus for this container | 103 | } |
102 | /* TODO WLR | 104 | |
103 | if (parent->type == C_WORKSPACE && child->type == C_VIEW && | 105 | struct sway_container *container_reap_empty(struct sway_container *container) { |
104 | (parent->workspace_layout == L_TABBED || parent->workspace_layout == | 106 | if (!sway_assert(container, "reaping null container")) { |
105 | L_STACKED)) { | 107 | return NULL; |
106 | child = new_container(child, parent->workspace_layout); | ||
107 | } | 108 | } |
108 | */ | 109 | wlr_log(L_DEBUG, "reaping %p %s", container, container->name); |
110 | while (container->children->length == 0) { | ||
111 | if (container->type == C_WORKSPACE) { | ||
112 | if (!workspace_is_visible(container)) { | ||
113 | struct sway_container *parent = container->parent; | ||
114 | container_workspace_destroy(container); | ||
115 | return parent; | ||
116 | } | ||
117 | return container; | ||
118 | } else if (container->type == C_CONTAINER) { | ||
119 | struct sway_container *parent = container->parent; | ||
120 | container_destroy(container); | ||
121 | container = parent; | ||
122 | } else { | ||
123 | container = container->parent; | ||
124 | } | ||
125 | } | ||
126 | return container; | ||
109 | } | 127 | } |
110 | 128 | ||
111 | struct sway_container *container_remove_child(struct sway_container *child) { | 129 | struct sway_container *container_remove_child(struct sway_container *child) { |
112 | int i; | ||
113 | struct sway_container *parent = child->parent; | 130 | struct sway_container *parent = child->parent; |
114 | for (i = 0; i < parent->children->length; ++i) { | 131 | for (int i = 0; i < parent->children->length; ++i) { |
115 | if (parent->children->items[i] == child) { | 132 | if (parent->children->items[i] == child) { |
116 | list_del(parent->children, i); | 133 | list_del(parent->children, i); |
117 | break; | 134 | break; |
118 | } | 135 | } |
119 | } | 136 | } |
120 | child->parent = NULL; | 137 | child->parent = NULL; |
121 | return parent; | 138 | return container_reap_empty(parent); |
139 | } | ||
140 | |||
141 | void container_move_to(struct sway_container* container, | ||
142 | struct sway_container* destination) { | ||
143 | if (container == destination | ||
144 | || container_has_anscestor(container, destination)) { | ||
145 | return; | ||
146 | } | ||
147 | struct sway_container *old_parent = container_remove_child(container); | ||
148 | container->width = container->height = 0; | ||
149 | struct sway_container *new_parent = | ||
150 | container_add_sibling(destination, container); | ||
151 | if (old_parent) { | ||
152 | arrange_windows(old_parent, -1, -1); | ||
153 | } | ||
154 | arrange_windows(new_parent, -1, -1); | ||
122 | } | 155 | } |
123 | 156 | ||
124 | enum sway_container_layout container_get_default_layout( | 157 | enum sway_container_layout container_get_default_layout( |
125 | struct sway_container *output) { | 158 | struct sway_container *output) { |
126 | /* TODO WLR | ||
127 | if (config->default_layout != L_NONE) { | 159 | if (config->default_layout != L_NONE) { |
128 | //return config->default_layout; | 160 | return config->default_layout; |
129 | } else if (config->default_orientation != L_NONE) { | 161 | } else if (config->default_orientation != L_NONE) { |
130 | return config->default_orientation; | 162 | return config->default_orientation; |
131 | } else */if (output->width >= output->height) { | 163 | } else if (output->width >= output->height) { |
132 | return L_HORIZ; | 164 | return L_HORIZ; |
133 | } else { | 165 | } else { |
134 | return L_VERT; | 166 | return L_VERT; |
diff --git a/sway/tree/output.c b/sway/tree/output.c new file mode 100644 index 00000000..7248fd00 --- /dev/null +++ b/sway/tree/output.c | |||
@@ -0,0 +1,39 @@ | |||
1 | #include "sway/tree/container.h" | ||
2 | #include "sway/tree/layout.h" | ||
3 | #include "sway/output.h" | ||
4 | #include "log.h" | ||
5 | |||
6 | struct sway_container *container_output_destroy(struct sway_container *output) { | ||
7 | if (!sway_assert(output, "cannot destroy null output")) { | ||
8 | return NULL; | ||
9 | } | ||
10 | |||
11 | if (output->children->length > 0) { | ||
12 | // TODO save workspaces when there are no outputs. | ||
13 | // TODO also check if there will ever be no outputs except for exiting | ||
14 | // program | ||
15 | if (root_container.children->length > 1) { | ||
16 | int p = root_container.children->items[0] == output; | ||
17 | // Move workspace from this output to another output | ||
18 | while (output->children->length) { | ||
19 | struct sway_container *child = output->children->items[0]; | ||
20 | container_remove_child(child); | ||
21 | container_add_child(root_container.children->items[p], child); | ||
22 | } | ||
23 | container_sort_workspaces(root_container.children->items[p]); | ||
24 | arrange_windows(root_container.children->items[p], | ||
25 | -1, -1); | ||
26 | } | ||
27 | } | ||
28 | |||
29 | wl_list_remove(&output->sway_output->destroy.link); | ||
30 | wl_list_remove(&output->sway_output->mode.link); | ||
31 | wl_list_remove(&output->sway_output->transform.link); | ||
32 | |||
33 | wl_list_remove(&output->sway_output->damage_destroy.link); | ||
34 | wl_list_remove(&output->sway_output->damage_frame.link); | ||
35 | |||
36 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); | ||
37 | container_destroy(output); | ||
38 | return &root_container; | ||
39 | } | ||
diff --git a/sway/tree/view.c b/sway/tree/view.c index d5325c31..b7d1a41b 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -1,5 +1,7 @@ | |||
1 | #include <wayland-server.h> | 1 | #include <wayland-server.h> |
2 | #include <wlr/types/wlr_output_layout.h> | 2 | #include <wlr/types/wlr_output_layout.h> |
3 | #include "log.h" | ||
4 | #include "sway/output.h" | ||
3 | #include "sway/tree/container.h" | 5 | #include "sway/tree/container.h" |
4 | #include "sway/tree/layout.h" | 6 | #include "sway/tree/layout.h" |
5 | #include "sway/tree/view.h" | 7 | #include "sway/tree/view.h" |
@@ -94,3 +96,28 @@ void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { | |||
94 | } | 96 | } |
95 | } | 97 | } |
96 | } | 98 | } |
99 | |||
100 | struct sway_container *container_view_destroy(struct sway_container *view) { | ||
101 | if (!view) { | ||
102 | return NULL; | ||
103 | } | ||
104 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); | ||
105 | struct sway_container *parent = container_destroy(view); | ||
106 | arrange_windows(parent, -1, -1); | ||
107 | return parent; | ||
108 | } | ||
109 | |||
110 | void view_damage_whole(struct sway_view *view) { | ||
111 | struct sway_container *cont = NULL; | ||
112 | for (int i = 0; i < root_container.children->length; ++i) { | ||
113 | cont = root_container.children->items[i]; | ||
114 | if (cont->type == C_OUTPUT) { | ||
115 | output_damage_whole_view(cont->sway_output, view); | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | |||
120 | void view_damage_from(struct sway_view *view) { | ||
121 | // TODO | ||
122 | view_damage_whole(view); | ||
123 | } | ||
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 5800ea09..c629f1f1 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -6,9 +6,10 @@ | |||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <strings.h> | 7 | #include <strings.h> |
8 | #include "stringop.h" | 8 | #include "stringop.h" |
9 | #include "sway/tree/container.h" | ||
10 | #include "sway/input/input-manager.h" | 9 | #include "sway/input/input-manager.h" |
11 | #include "sway/input/seat.h" | 10 | #include "sway/input/seat.h" |
11 | #include "sway/ipc-server.h" | ||
12 | #include "sway/tree/container.h" | ||
12 | #include "sway/tree/workspace.h" | 13 | #include "sway/tree/workspace.h" |
13 | #include "log.h" | 14 | #include "log.h" |
14 | #include "util.h" | 15 | #include "util.h" |
@@ -202,7 +203,48 @@ struct sway_container *workspace_create(const char *name) { | |||
202 | sway_seat_get_focus_inactive(seat, &root_container); | 203 | sway_seat_get_focus_inactive(seat, &root_container); |
203 | parent = focus; | 204 | parent = focus; |
204 | parent = container_parent(parent, C_OUTPUT); | 205 | parent = container_parent(parent, C_OUTPUT); |
205 | return container_workspace_create(parent, name); | 206 | struct sway_container *new_ws = container_workspace_create(parent, name); |
207 | ipc_event_workspace(NULL, new_ws, "init"); | ||
208 | return new_ws; | ||
209 | } | ||
210 | |||
211 | struct sway_container *container_workspace_destroy( | ||
212 | struct sway_container *workspace) { | ||
213 | if (!sway_assert(workspace, "cannot destroy null workspace")) { | ||
214 | return NULL; | ||
215 | } | ||
216 | |||
217 | // Do not destroy this if it's the last workspace on this output | ||
218 | struct sway_container *output = container_parent(workspace, C_OUTPUT); | ||
219 | if (output && output->children->length == 1) { | ||
220 | return NULL; | ||
221 | } | ||
222 | |||
223 | struct sway_container *parent = workspace->parent; | ||
224 | if (workspace->children->length == 0) { | ||
225 | // destroy the WS if there are no children (TODO check for floating) | ||
226 | wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); | ||
227 | ipc_event_workspace(workspace, NULL, "empty"); | ||
228 | } else { | ||
229 | // Move children to a different workspace on this output | ||
230 | struct sway_container *new_workspace = NULL; | ||
231 | // TODO move floating | ||
232 | for (int i = 0; i < output->children->length; i++) { | ||
233 | if (output->children->items[i] != workspace) { | ||
234 | new_workspace = output->children->items[i]; | ||
235 | break; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", | ||
240 | workspace->name, new_workspace->name); | ||
241 | for (int i = 0; i < workspace->children->length; i++) { | ||
242 | container_move_to(workspace->children->items[i], new_workspace); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | container_destroy(workspace); | ||
247 | return parent; | ||
206 | } | 248 | } |
207 | 249 | ||
208 | /** | 250 | /** |
@@ -343,3 +385,13 @@ bool workspace_switch(struct sway_container *workspace) { | |||
343 | arrange_windows(output, -1, -1); | 385 | arrange_windows(output, -1, -1); |
344 | return true; | 386 | return true; |
345 | } | 387 | } |
388 | |||
389 | bool workspace_is_visible(struct sway_container *ws) { | ||
390 | struct sway_container *output = container_parent(ws, C_OUTPUT); | ||
391 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
392 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); | ||
393 | if (focus->type != C_WORKSPACE) { | ||
394 | focus = container_parent(focus, C_WORKSPACE); | ||
395 | } | ||
396 | return focus == ws; | ||
397 | } | ||
diff --git a/swaybg/main.c b/swaybg/main.c index f431526c..203082f6 100644 --- a/swaybg/main.c +++ b/swaybg/main.c | |||
@@ -300,6 +300,7 @@ int main(int argc, const char **argv) { | |||
300 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | | 300 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | |
301 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | | 301 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | |
302 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); | 302 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); |
303 | zwlr_layer_surface_v1_set_exclusive_zone(state.layer_surface, -1); | ||
303 | zwlr_layer_surface_v1_add_listener(state.layer_surface, | 304 | zwlr_layer_surface_v1_add_listener(state.layer_surface, |
304 | &layer_surface_listener, &state); | 305 | &layer_surface_listener, &state); |
305 | state.run_display = true; | 306 | state.run_display = true; |