aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/container.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r--sway/tree/container.c122
1 files changed, 90 insertions, 32 deletions
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}