diff options
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 113 |
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 | ||
79 | static 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 | |||
104 | struct sway_container *container_create(enum sway_container_type type) { | 79 | struct 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 | */ | ||
757 | static 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 | |||
780 | static void update_title_texture(struct sway_container *con, | 765 | static 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 | |||
1261 | static 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 | |||
1267 | static 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 | |||
1273 | void 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 | } | ||