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.c113
1 files changed, 81 insertions, 32 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index ea20991c..80d3f524 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:
@@ -777,13 +750,25 @@ void container_damage_whole(struct sway_container *container) {
777 } 750 }
778} 751}
779 752
753/**
754 * Return the output which will be used for scale purposes.
755 * This is the most recently entered output.
756 */
757static struct sway_output *container_get_effective_output(
758 struct sway_container *con) {
759 if (con->outputs->length == 0) {
760 return NULL;
761 }
762 return con->outputs->items[con->outputs->length - 1];
763}
764
780static void update_title_texture(struct sway_container *con, 765static void update_title_texture(struct sway_container *con,
781 struct wlr_texture **texture, struct border_colors *class) { 766 struct wlr_texture **texture, struct border_colors *class) {
782 if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW, 767 if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
783 "Unexpected type %s", container_type_to_str(con->type))) { 768 "Unexpected type %s", container_type_to_str(con->type))) {
784 return; 769 return;
785 } 770 }
786 struct sway_container *output = container_parent(con, C_OUTPUT); 771 struct sway_output *output = container_get_effective_output(con);
787 if (!output) { 772 if (!output) {
788 return; 773 return;
789 } 774 }
@@ -795,7 +780,7 @@ static void update_title_texture(struct sway_container *con,
795 return; 780 return;
796 } 781 }
797 782
798 double scale = output->sway_output->wlr_output->scale; 783 double scale = output->wlr_output->scale;
799 int width = 0; 784 int width = 0;
800 int height = con->title_height * scale; 785 int height = con->title_height * scale;
801 786
@@ -823,7 +808,7 @@ static void update_title_texture(struct sway_container *con,
823 unsigned char *data = cairo_image_surface_get_data(surface); 808 unsigned char *data = cairo_image_surface_get_data(surface);
824 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); 809 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
825 struct wlr_renderer *renderer = wlr_backend_get_renderer( 810 struct wlr_renderer *renderer = wlr_backend_get_renderer(
826 output->sway_output->wlr_output->backend); 811 output->wlr_output->backend);
827 *texture = wlr_texture_from_pixels( 812 *texture = wlr_texture_from_pixels(
828 renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data); 813 renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data);
829 cairo_surface_destroy(surface); 814 cairo_surface_destroy(surface);
@@ -1272,3 +1257,67 @@ bool container_is_fullscreen_or_child(struct sway_container *container) {
1272 1257
1273 return false; 1258 return false;
1274} 1259}
1260
1261static void surface_send_enter_iterator(struct wlr_surface *surface,
1262 int x, int y, void *data) {
1263 struct wlr_output *wlr_output = data;
1264 wlr_surface_send_enter(surface, wlr_output);
1265}
1266
1267static void surface_send_leave_iterator(struct wlr_surface *surface,
1268 int x, int y, void *data) {
1269 struct wlr_output *wlr_output = data;
1270 wlr_surface_send_leave(surface, wlr_output);
1271}
1272
1273void container_discover_outputs(struct sway_container *con) {
1274 if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
1275 "Expected a container or view")) {
1276 return;
1277 }
1278 struct wlr_box con_box = {
1279 .x = con->current.swayc_x,
1280 .y = con->current.swayc_y,
1281 .width = con->current.swayc_width,
1282 .height = con->current.swayc_height,
1283 };
1284 struct sway_output *old_output = container_get_effective_output(con);
1285
1286 for (int i = 0; i < root_container.children->length; ++i) {
1287 struct sway_container *output = root_container.children->items[i];
1288 struct sway_output *sway_output = output->sway_output;
1289 struct wlr_box output_box;
1290 container_get_box(output, &output_box);
1291 struct wlr_box intersection;
1292 bool intersects =
1293 wlr_box_intersection(&con_box, &output_box, &intersection);
1294 int index = list_find(con->outputs, sway_output);
1295
1296 if (intersects && index == -1) {
1297 // Send enter
1298 wlr_log(WLR_DEBUG, "Con %p entered output %p", con, sway_output);
1299 if (con->type == C_VIEW) {
1300 view_for_each_surface(con->sway_view,
1301 surface_send_enter_iterator, sway_output->wlr_output);
1302 }
1303 list_add(con->outputs, sway_output);
1304 } else if (!intersects && index != -1) {
1305 // Send leave
1306 wlr_log(WLR_DEBUG, "Con %p left output %p", con, sway_output);
1307 if (con->type == C_VIEW) {
1308 view_for_each_surface(con->sway_view,
1309 surface_send_leave_iterator, sway_output->wlr_output);
1310 }
1311 list_del(con->outputs, index);
1312 }
1313 }
1314 struct sway_output *new_output = container_get_effective_output(con);
1315 double old_scale = old_output ? old_output->wlr_output->scale : -1;
1316 double new_scale = new_output ? new_output->wlr_output->scale : -1;
1317 if (old_scale != new_scale) {
1318 container_update_title_textures(con);
1319 if (con->type == C_VIEW) {
1320 view_update_marks_textures(con->sway_view);
1321 }
1322 }
1323}