aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/tree/container.h16
-rw-r--r--include/sway/tree/view.h1
-rw-r--r--sway/commands/move.c1
-rw-r--r--sway/desktop/transaction.c3
-rw-r--r--sway/tree/container.c122
-rw-r--r--sway/tree/layout.c8
-rw-r--r--sway/tree/view.c54
7 files changed, 107 insertions, 98 deletions
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index 5eccedc1..cd886cd0 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -138,6 +138,9 @@ struct sway_container {
138 138
139 struct sway_container *parent; 139 struct sway_container *parent;
140 140
141 // Outputs currently being intersected
142 list_t *outputs; // struct sway_output
143
141 // Indicates that the container is a scratchpad container. 144 // Indicates that the container is a scratchpad container.
142 // Both hidden and visible scratchpad containers have scratchpad=true. 145 // Both hidden and visible scratchpad containers have scratchpad=true.
143 // Hidden scratchpad containers have a NULL parent. 146 // Hidden scratchpad containers have a NULL parent.
@@ -166,12 +169,7 @@ struct sway_container {
166 169
167 struct { 170 struct {
168 struct wl_signal destroy; 171 struct wl_signal destroy;
169 // Raised after the tree updates, but before arrange_windows
170 // Passed the previous parent
171 struct wl_signal reparent;
172 } events; 172 } events;
173
174 struct wl_listener reparent;
175}; 173};
176 174
177struct sway_container *container_create(enum sway_container_type type); 175struct sway_container *container_create(enum sway_container_type type);
@@ -353,4 +351,12 @@ bool container_is_floating_or_child(struct sway_container *container);
353 */ 351 */
354bool container_is_fullscreen_or_child(struct sway_container *container); 352bool container_is_fullscreen_or_child(struct sway_container *container);
355 353
354/**
355 * Return the output which will be used for scale purposes.
356 * This is the most recently entered output.
357 */
358struct sway_output *container_get_effective_output(struct sway_container *con);
359
360void container_discover_outputs(struct sway_container *con);
361
356#endif 362#endif
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 2747e7c4..5fdecc2b 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -120,7 +120,6 @@ struct sway_view {
120 } events; 120 } events;
121 121
122 struct wl_listener surface_new_subsurface; 122 struct wl_listener surface_new_subsurface;
123 struct wl_listener container_reparent;
124}; 123};
125 124
126struct sway_xdg_shell_v6_view { 125struct sway_xdg_shell_v6_view {
diff --git a/sway/commands/move.c b/sway/commands/move.c
index e788d32f..c6dc0775 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -236,7 +236,6 @@ static void workspace_move_to_output(struct sway_container *workspace,
236 seat_get_focus_inactive(seat, output); 236 seat_get_focus_inactive(seat, output);
237 237
238 container_add_child(output, workspace); 238 container_add_child(output, workspace);
239 wl_signal_emit(&workspace->events.reparent, old_output);
240 239
241 // If moving the last workspace from the old output, create a new workspace 240 // If moving the last workspace from the old output, create a new workspace
242 // on the old output 241 // on the old output
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index 3b626cb7..f82e5ef2 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -195,6 +195,9 @@ static void transaction_apply(struct sway_transaction *transaction) {
195 } 195 }
196 196
197 container->instruction = NULL; 197 container->instruction = NULL;
198 if (container->type == C_CONTAINER || container->type == C_VIEW) {
199 container_discover_outputs(container);
200 }
198 } 201 }
199} 202}
200 203
diff --git a/sway/tree/container.c b/sway/tree/container.c
index ea20991c..6ea0cc94 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -76,31 +76,6 @@ void container_update_textures_recursive(struct sway_container *con) {
76 } 76 }
77} 77}
78 78
79static void handle_reparent(struct wl_listener *listener,
80 void *data) {
81 struct sway_container *container =
82 wl_container_of(listener, container, reparent);
83 struct sway_container *old_parent = data;
84
85 struct sway_container *old_output = old_parent;
86 if (old_output != NULL && old_output->type != C_OUTPUT) {
87 old_output = container_parent(old_output, C_OUTPUT);
88 }
89
90 struct sway_container *new_output = container->parent;
91 if (new_output != NULL && new_output->type != C_OUTPUT) {
92 new_output = container_parent(new_output, C_OUTPUT);
93 }
94
95 if (old_output && new_output) {
96 float old_scale = old_output->sway_output->wlr_output->scale;
97 float new_scale = new_output->sway_output->wlr_output->scale;
98 if (old_scale != new_scale) {
99 container_update_textures_recursive(container);
100 }
101 }
102}
103
104struct sway_container *container_create(enum sway_container_type type) { 79struct sway_container *container_create(enum sway_container_type type) {
105 // next id starts at 1 because 0 is assigned to root_container in layout.c 80 // next id starts at 1 because 0 is assigned to root_container in layout.c
106 static size_t next_id = 1; 81 static size_t next_id = 1;
@@ -117,12 +92,9 @@ struct sway_container *container_create(enum sway_container_type type) {
117 c->children = create_list(); 92 c->children = create_list();
118 c->current.children = create_list(); 93 c->current.children = create_list();
119 } 94 }
95 c->outputs = create_list();
120 96
121 wl_signal_init(&c->events.destroy); 97 wl_signal_init(&c->events.destroy);
122 wl_signal_init(&c->events.reparent);
123
124 wl_signal_add(&c->events.reparent, &c->reparent);
125 c->reparent.notify = handle_reparent;
126 98
127 c->has_gaps = false; 99 c->has_gaps = false;
128 c->gaps_inner = 0; 100 c->gaps_inner = 0;
@@ -156,6 +128,7 @@ void container_free(struct sway_container *cont) {
156 wlr_texture_destroy(cont->title_urgent); 128 wlr_texture_destroy(cont->title_urgent);
157 list_free(cont->children); 129 list_free(cont->children);
158 list_free(cont->current.children); 130 list_free(cont->current.children);
131 list_free(cont->outputs);
159 132
160 switch (cont->type) { 133 switch (cont->type) {
161 case C_ROOT: 134 case C_ROOT:
@@ -238,6 +211,14 @@ static struct sway_container *container_workspace_destroy(
238 return output; 211 return output;
239} 212}
240 213
214static void untrack_output(struct sway_container *con, void *data) {
215 struct sway_output *output = data;
216 int index = list_find(con->outputs, output);
217 if (index != -1) {
218 list_del(con->outputs, index);
219 }
220}
221
241static struct sway_container *container_output_destroy( 222static struct sway_container *container_output_destroy(
242 struct sway_container *output) { 223 struct sway_container *output) {
243 if (!sway_assert(output, "cannot destroy null output")) { 224 if (!sway_assert(output, "cannot destroy null output")) {
@@ -279,6 +260,8 @@ static struct sway_container *container_output_destroy(
279 } 260 }
280 } 261 }
281 262
263 root_for_each_container(untrack_output, output->sway_output);
264
282 wl_list_remove(&output->sway_output->mode.link); 265 wl_list_remove(&output->sway_output->mode.link);
283 wl_list_remove(&output->sway_output->transform.link); 266 wl_list_remove(&output->sway_output->transform.link);
284 wl_list_remove(&output->sway_output->scale.link); 267 wl_list_remove(&output->sway_output->scale.link);
@@ -777,13 +760,24 @@ void container_damage_whole(struct sway_container *container) {
777 } 760 }
778} 761}
779 762
763/**
764 * Return the output which will be used for scale purposes.
765 * This is the most recently entered output.
766 */
767struct sway_output *container_get_effective_output(struct sway_container *con) {
768 if (con->outputs->length == 0) {
769 return NULL;
770 }
771 return con->outputs->items[con->outputs->length - 1];
772}
773
780static void update_title_texture(struct sway_container *con, 774static void update_title_texture(struct sway_container *con,
781 struct wlr_texture **texture, struct border_colors *class) { 775 struct wlr_texture **texture, struct border_colors *class) {
782 if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW, 776 if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
783 "Unexpected type %s", container_type_to_str(con->type))) { 777 "Unexpected type %s", container_type_to_str(con->type))) {
784 return; 778 return;
785 } 779 }
786 struct sway_container *output = container_parent(con, C_OUTPUT); 780 struct sway_output *output = container_get_effective_output(con);
787 if (!output) { 781 if (!output) {
788 return; 782 return;
789 } 783 }
@@ -795,7 +789,7 @@ static void update_title_texture(struct sway_container *con,
795 return; 789 return;
796 } 790 }
797 791
798 double scale = output->sway_output->wlr_output->scale; 792 double scale = output->wlr_output->scale;
799 int width = 0; 793 int width = 0;
800 int height = con->title_height * scale; 794 int height = con->title_height * scale;
801 795
@@ -823,7 +817,7 @@ static void update_title_texture(struct sway_container *con,
823 unsigned char *data = cairo_image_surface_get_data(surface); 817 unsigned char *data = cairo_image_surface_get_data(surface);
824 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); 818 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
825 struct wlr_renderer *renderer = wlr_backend_get_renderer( 819 struct wlr_renderer *renderer = wlr_backend_get_renderer(
826 output->sway_output->wlr_output->backend); 820 output->wlr_output->backend);
827 *texture = wlr_texture_from_pixels( 821 *texture = wlr_texture_from_pixels(
828 renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data); 822 renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data);
829 cairo_surface_destroy(surface); 823 cairo_surface_destroy(surface);
@@ -1272,3 +1266,67 @@ bool container_is_fullscreen_or_child(struct sway_container *container) {
1272 1266
1273 return false; 1267 return false;
1274} 1268}
1269
1270static void surface_send_enter_iterator(struct wlr_surface *surface,
1271 int x, int y, void *data) {
1272 struct wlr_output *wlr_output = data;
1273 wlr_surface_send_enter(surface, wlr_output);
1274}
1275
1276static void surface_send_leave_iterator(struct wlr_surface *surface,
1277 int x, int y, void *data) {
1278 struct wlr_output *wlr_output = data;
1279 wlr_surface_send_leave(surface, wlr_output);
1280}
1281
1282void container_discover_outputs(struct sway_container *con) {
1283 if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
1284 "Expected a container or view")) {
1285 return;
1286 }
1287 struct wlr_box con_box = {
1288 .x = con->current.swayc_x,
1289 .y = con->current.swayc_y,
1290 .width = con->current.swayc_width,
1291 .height = con->current.swayc_height,
1292 };
1293 struct sway_output *old_output = container_get_effective_output(con);
1294
1295 for (int i = 0; i < root_container.children->length; ++i) {
1296 struct sway_container *output = root_container.children->items[i];
1297 struct sway_output *sway_output = output->sway_output;
1298 struct wlr_box output_box;
1299 container_get_box(output, &output_box);
1300 struct wlr_box intersection;
1301 bool intersects =
1302 wlr_box_intersection(&con_box, &output_box, &intersection);
1303 int index = list_find(con->outputs, sway_output);
1304
1305 if (intersects && index == -1) {
1306 // Send enter
1307 wlr_log(WLR_DEBUG, "Con %p entered output %p", con, sway_output);
1308 if (con->type == C_VIEW) {
1309 view_for_each_surface(con->sway_view,
1310 surface_send_enter_iterator, sway_output->wlr_output);
1311 }
1312 list_add(con->outputs, sway_output);
1313 } else if (!intersects && index != -1) {
1314 // Send leave
1315 wlr_log(WLR_DEBUG, "Con %p left output %p", con, sway_output);
1316 if (con->type == C_VIEW) {
1317 view_for_each_surface(con->sway_view,
1318 surface_send_leave_iterator, sway_output->wlr_output);
1319 }
1320 list_del(con->outputs, index);
1321 }
1322 }
1323 struct sway_output *new_output = container_get_effective_output(con);
1324 double old_scale = old_output ? old_output->wlr_output->scale : -1;
1325 double new_scale = new_output ? new_output->wlr_output->scale : -1;
1326 if (old_scale != new_scale) {
1327 container_update_title_textures(con);
1328 if (con->type == C_VIEW) {
1329 view_update_marks_textures(con->sway_view);
1330 }
1331 }
1332}
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index 2f22a3dd..ee7d7418 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -75,7 +75,6 @@ void container_insert_child(struct sway_container *parent,
75 list_insert(parent->children, i, child); 75 list_insert(parent->children, i, child);
76 child->parent = parent; 76 child->parent = parent;
77 container_handle_fullscreen_reparent(child, old_parent); 77 container_handle_fullscreen_reparent(child, old_parent);
78 wl_signal_emit(&child->events.reparent, old_parent);
79} 78}
80 79
81struct sway_container *container_add_sibling(struct sway_container *fixed, 80struct sway_container *container_add_sibling(struct sway_container *fixed,
@@ -91,7 +90,6 @@ struct sway_container *container_add_sibling(struct sway_container *fixed,
91 list_insert(parent->children, i + 1, active); 90 list_insert(parent->children, i + 1, active);
92 active->parent = parent; 91 active->parent = parent;
93 container_handle_fullscreen_reparent(active, old_parent); 92 container_handle_fullscreen_reparent(active, old_parent);
94 wl_signal_emit(&active->events.reparent, old_parent);
95 return active->parent; 93 return active->parent;
96} 94}
97 95
@@ -181,8 +179,6 @@ void container_move_to(struct sway_container *container,
181 } 179 }
182 } 180 }
183 181
184 wl_signal_emit(&container->events.reparent, old_parent);
185
186 if (container->type == C_VIEW) { 182 if (container->type == C_VIEW) {
187 ipc_event_window(container, "move"); 183 ipc_event_window(container, "move");
188 } 184 }
@@ -307,7 +303,6 @@ static void workspace_rejigger(struct sway_container *ws,
307 303
308 container_flatten(ws); 304 container_flatten(ws);
309 container_reap_empty_recursive(original_parent); 305 container_reap_empty_recursive(original_parent);
310 wl_signal_emit(&child->events.reparent, original_parent);
311 container_create_notify(new_parent); 306 container_create_notify(new_parent);
312} 307}
313 308
@@ -859,7 +854,6 @@ struct sway_container *container_split(struct sway_container *child,
859 struct sway_container *ws_child = workspace->children->items[0]; 854 struct sway_container *ws_child = workspace->children->items[0];
860 container_remove_child(ws_child); 855 container_remove_child(ws_child);
861 container_add_child(cont, ws_child); 856 container_add_child(cont, ws_child);
862 wl_signal_emit(&ws_child->events.reparent, workspace);
863 } 857 }
864 858
865 container_add_child(workspace, cont); 859 container_add_child(workspace, cont);
@@ -867,11 +861,9 @@ struct sway_container *container_split(struct sway_container *child,
867 workspace->layout = layout; 861 workspace->layout = layout;
868 cont->layout = old_layout; 862 cont->layout = old_layout;
869 } else { 863 } else {
870 struct sway_container *old_parent = child->parent;
871 cont->layout = layout; 864 cont->layout = layout;
872 container_replace_child(child, cont); 865 container_replace_child(child, cont);
873 container_add_child(cont, child); 866 container_add_child(cont, child);
874 wl_signal_emit(&child->events.reparent, old_parent);
875 } 867 }
876 868
877 if (set_focus) { 869 if (set_focus) {
diff --git a/sway/tree/view.c b/sway/tree/view.c
index b77a9bb2..2c0c1aa9 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -364,48 +364,6 @@ static void view_handle_surface_new_subsurface(struct wl_listener *listener,
364 view_subsurface_create(view, subsurface); 364 view_subsurface_create(view, subsurface);
365} 365}
366 366
367static void surface_send_enter_iterator(struct wlr_surface *surface,
368 int x, int y, void *data) {
369 struct wlr_output *wlr_output = data;
370 wlr_surface_send_enter(surface, wlr_output);
371}
372
373static void surface_send_leave_iterator(struct wlr_surface *surface,
374 int x, int y, void *data) {
375 struct wlr_output *wlr_output = data;
376 wlr_surface_send_leave(surface, wlr_output);
377}
378
379static void view_handle_container_reparent(struct wl_listener *listener,
380 void *data) {
381 struct sway_view *view =
382 wl_container_of(listener, view, container_reparent);
383 struct sway_container *old_parent = data;
384
385 struct sway_container *old_output = old_parent;
386 if (old_output != NULL && old_output->type != C_OUTPUT) {
387 old_output = container_parent(old_output, C_OUTPUT);
388 }
389
390 struct sway_container *new_output = view->swayc->parent;
391 if (new_output != NULL && new_output->type != C_OUTPUT) {
392 new_output = container_parent(new_output, C_OUTPUT);
393 }
394
395 if (old_output == new_output) {
396 return;
397 }
398
399 if (old_output != NULL) {
400 view_for_each_surface(view, surface_send_leave_iterator,
401 old_output->sway_output->wlr_output);
402 }
403 if (new_output != NULL) {
404 view_for_each_surface(view, surface_send_enter_iterator,
405 new_output->sway_output->wlr_output);
406 }
407}
408
409static bool view_has_executed_criteria(struct sway_view *view, 367static bool view_has_executed_criteria(struct sway_view *view,
410 struct criteria *criteria) { 368 struct criteria *criteria) {
411 for (int i = 0; i < view->executed_criteria->length; ++i) { 369 for (int i = 0; i < view->executed_criteria->length; ++i) {
@@ -567,9 +525,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
567 &view->surface_new_subsurface); 525 &view->surface_new_subsurface);
568 view->surface_new_subsurface.notify = view_handle_surface_new_subsurface; 526 view->surface_new_subsurface.notify = view_handle_surface_new_subsurface;
569 527
570 wl_signal_add(&view->swayc->events.reparent, &view->container_reparent);
571 view->container_reparent.notify = view_handle_container_reparent;
572
573 if (view->impl->wants_floating && view->impl->wants_floating(view)) { 528 if (view->impl->wants_floating && view->impl->wants_floating(view)) {
574 view->border = config->floating_border; 529 view->border = config->floating_border;
575 view->border_thickness = config->floating_border_thickness; 530 view->border_thickness = config->floating_border_thickness;
@@ -587,15 +542,12 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
587 view_update_title(view, false); 542 view_update_title(view, false);
588 container_notify_subtree_changed(view->swayc->parent); 543 container_notify_subtree_changed(view->swayc->parent);
589 view_execute_criteria(view); 544 view_execute_criteria(view);
590
591 view_handle_container_reparent(&view->container_reparent, NULL);
592} 545}
593 546
594void view_unmap(struct sway_view *view) { 547void view_unmap(struct sway_view *view) {
595 wl_signal_emit(&view->events.unmap, view); 548 wl_signal_emit(&view->events.unmap, view);
596 549
597 wl_list_remove(&view->surface_new_subsurface.link); 550 wl_list_remove(&view->surface_new_subsurface.link);
598 wl_list_remove(&view->container_reparent.link);
599 551
600 if (view->urgent_timer) { 552 if (view->urgent_timer) {
601 wl_event_source_remove(view->urgent_timer); 553 wl_event_source_remove(view->urgent_timer);
@@ -937,7 +889,7 @@ void view_add_mark(struct sway_view *view, char *mark) {
937 889
938static void update_marks_texture(struct sway_view *view, 890static void update_marks_texture(struct sway_view *view,
939 struct wlr_texture **texture, struct border_colors *class) { 891 struct wlr_texture **texture, struct border_colors *class) {
940 struct sway_container *output = container_parent(view->swayc, C_OUTPUT); 892 struct sway_output *output = container_get_effective_output(view->swayc);
941 if (!output) { 893 if (!output) {
942 return; 894 return;
943 } 895 }
@@ -973,7 +925,7 @@ static void update_marks_texture(struct sway_view *view,
973 } 925 }
974 free(part); 926 free(part);
975 927
976 double scale = output->sway_output->wlr_output->scale; 928 double scale = output->wlr_output->scale;
977 int width = 0; 929 int width = 0;
978 int height = view->swayc->title_height * scale; 930 int height = view->swayc->title_height * scale;
979 931
@@ -999,7 +951,7 @@ static void update_marks_texture(struct sway_view *view,
999 unsigned char *data = cairo_image_surface_get_data(surface); 951 unsigned char *data = cairo_image_surface_get_data(surface);
1000 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); 952 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
1001 struct wlr_renderer *renderer = wlr_backend_get_renderer( 953 struct wlr_renderer *renderer = wlr_backend_get_renderer(
1002 output->sway_output->wlr_output->backend); 954 output->wlr_output->backend);
1003 *texture = wlr_texture_from_pixels( 955 *texture = wlr_texture_from_pixels(
1004 renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data); 956 renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data);
1005 cairo_surface_destroy(surface); 957 cairo_surface_destroy(surface);