From b3ee9af0c837bcb48eb30021eaa42c882426e66a Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 2 Jul 2018 23:06:44 +0100 Subject: [PATCH 1/9] Add view_get_geometry --- include/sway/tree/view.h | 5 +---- sway/desktop/xdg_shell.c | 14 ++++++++++++- sway/desktop/xwayland.c | 2 -- sway/tree/view.c | 44 +++++++++++++--------------------------- 4 files changed, 28 insertions(+), 37 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index c2225bcb9..1ded601cf 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -38,6 +38,7 @@ struct sway_view_impl { const char *(*get_string_prop)(struct sway_view *view, enum sway_view_prop prop); uint32_t (*get_int_prop)(struct sway_view *view, enum sway_view_prop prop); + void (*get_geometry)(struct sway_view *view, struct wlr_box *box); uint32_t (*configure)(struct sway_view *view, double lx, double ly, int width, int height); void (*set_activated)(struct sway_view *view, bool activated); @@ -285,10 +286,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); void view_unmap(struct sway_view *view); -void view_update_position(struct sway_view *view, double lx, double ly); - -void view_update_size(struct sway_view *view, int width, int height); - void view_child_init(struct sway_view_child *child, const struct sway_view_child_impl *impl, struct sway_view *view, struct wlr_surface *surface); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 6a7a3f7fc..2b2603577 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -107,7 +107,8 @@ static void get_constraints(struct sway_view *view, double *min_width, *max_height = state->max_height > 0 ? state->max_height : DBL_MAX; } -static const char *get_string_prop(struct sway_view *view, enum sway_view_prop prop) { +static const char *get_string_prop(struct sway_view *view, + enum sway_view_prop prop) { if (xdg_shell_view_from_view(view) == NULL) { return NULL; } @@ -121,6 +122,16 @@ static const char *get_string_prop(struct sway_view *view, enum sway_view_prop p } } +static void get_geometry(struct sway_view *view, struct wlr_box *box) { + struct sway_xdg_shell_view *xdg_shell_view = + xdg_shell_view_from_view(view); + if (xdg_shell_view == NULL) { + return; + } + struct wlr_xdg_surface *surface = view->wlr_xdg_surface; + wlr_xdg_surface_get_geometry(surface, box); +} + static uint32_t configure(struct sway_view *view, double lx, double ly, int width, int height) { struct sway_xdg_shell_view *xdg_shell_view = @@ -231,6 +242,7 @@ static void destroy(struct sway_view *view) { static const struct sway_view_impl view_impl = { .get_constraints = get_constraints, .get_string_prop = get_string_prop, + .get_geometry = get_geometry, .configure = configure, .set_activated = set_activated, .set_tiled = set_tiled, diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 14f59b9c3..dca62fb1b 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -287,8 +287,6 @@ static void handle_commit(struct wl_listener *listener, void *data) { if (view->swayc->instruction) { transaction_notify_view_ready_by_size(view, surface_state->width, surface_state->height); - } else if (container_is_floating(view->swayc)) { - view_update_size(view, surface_state->width, surface_state->height); } view_damage_from(view); diff --git a/sway/tree/view.c b/sway/tree/view.c index 950494d8b..fba0b52d3 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -162,6 +162,20 @@ void view_get_constraints(struct sway_view *view, double *min_width, } } +void view_get_geometry(struct sway_view *view, struct wlr_box *box) { + if (view->surface == NULL) { + box->x = box->y = box->width = box->height = 0; + return; + } + if (view->impl->get_geometry) { + view->impl->get_geometry(view, box); + return; + } + box->x = box->y = 0; + box->width = view->surface->current.width; + box->height = view->surface->current.height; +} + uint32_t view_configure(struct sway_view *view, double lx, double ly, int width, int height) { if (view->impl->configure) { @@ -615,36 +629,6 @@ void view_unmap(struct sway_view *view) { view->surface = NULL; } -void view_update_position(struct sway_view *view, double lx, double ly) { - if (view->x == lx && view->y == ly) { - return; - } - container_damage_whole(view->swayc); - view->x = lx; - view->y = ly; - view->swayc->current.view_x = lx; - view->swayc->current.view_y = ly; - if (container_is_floating(view->swayc)) { - container_set_geometry_from_floating_view(view->swayc); - } - container_damage_whole(view->swayc); -} - -void view_update_size(struct sway_view *view, int width, int height) { - if (view->width == width && view->height == height) { - return; - } - container_damage_whole(view->swayc); - view->width = width; - view->height = height; - view->swayc->current.view_width = width; - view->swayc->current.view_height = height; - if (container_is_floating(view->swayc)) { - container_set_geometry_from_floating_view(view->swayc); - } - container_damage_whole(view->swayc); -} - static void view_subsurface_create(struct sway_view *view, struct wlr_subsurface *subsurface) { struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child)); From 982a2d0c99f4128a7cf2236ca190dd9b4e6d7828 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 16 Aug 2018 22:41:10 +1000 Subject: [PATCH 2/9] Fix geometry --- include/sway/tree/view.h | 3 +++ sway/desktop/output.c | 8 ++++++-- sway/desktop/render.c | 10 ++++++++-- sway/desktop/transaction.c | 41 ++++++++++++++++++++++++++++++++------ sway/tree/container.c | 5 +++++ 5 files changed, 57 insertions(+), 10 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 1ded601cf..0e7f166cf 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -88,6 +88,7 @@ struct sway_view { struct wlr_buffer *saved_buffer; int saved_buffer_width, saved_buffer_height; + struct wlr_box saved_geometry; // The "old" geometry during a transaction bool destroying; @@ -242,6 +243,8 @@ const char *view_get_shell(struct sway_view *view); void view_get_constraints(struct sway_view *view, double *min_width, double *max_width, double *min_height, double *max_height); +void view_get_geometry(struct sway_view *view, struct wlr_box *box); + uint32_t view_configure(struct sway_view *view, double lx, double ly, int width, int height); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 66747a3f8..cb0b4a070 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -140,12 +140,16 @@ void output_surface_for_each_surface(struct sway_output *output, void output_view_for_each_surface(struct sway_output *output, struct sway_view *view, sway_surface_iterator_func_t iterator, void *user_data) { + struct wlr_box geometry; + view_get_geometry(view, &geometry); struct surface_iterator_data data = { .user_iterator = iterator, .user_data = user_data, .output = output, - .ox = view->swayc->current.view_x - output->swayc->current.swayc_x, - .oy = view->swayc->current.view_y - output->swayc->current.swayc_y, + .ox = view->swayc->current.view_x - output->swayc->current.swayc_x + - geometry.x, + .oy = view->swayc->current.view_y - output->swayc->current.swayc_y + - geometry.y, .width = view->swayc->current.view_width, .height = view->swayc->current.view_height, .rotation = 0, // TODO diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 6e1e31f03..93fcfbf49 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -192,10 +192,12 @@ static void render_view_toplevels(struct sway_view *view, .damage = damage, .alpha = alpha, }; + struct wlr_box geometry; + view_get_geometry(view, &geometry); // Render all toplevels without descending into popups output_surface_for_each_surface(output, view->surface, - view->swayc->current.view_x - output->wlr_output->lx, - view->swayc->current.view_y - output->wlr_output->ly, + view->swayc->current.view_x - output->wlr_output->lx - geometry.x, + view->swayc->current.view_y - output->wlr_output->ly - geometry.y, render_surface_iterator, &data); } @@ -232,6 +234,10 @@ static void render_saved_view(struct sway_view *view, .width = view->saved_buffer_width, .height = view->saved_buffer_height, }; + struct wlr_box geometry; + view_get_geometry(view, &geometry); + box.x -= geometry.x; + box.y -= geometry.y; struct wlr_box output_box = { .width = output->swayc->current.swayc_width, diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index e89f01d8b..7383c4550 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -170,23 +170,49 @@ static void transaction_apply(struct sway_transaction *transaction) { struct sway_container *container = instruction->container; // Damage the old and new locations - struct wlr_box old_box = { + struct wlr_box old_con_box = { .x = container->current.swayc_x, .y = container->current.swayc_y, .width = container->current.swayc_width, .height = container->current.swayc_height, }; - struct wlr_box new_box = { + struct wlr_box new_con_box = { .x = instruction->state.swayc_x, .y = instruction->state.swayc_y, .width = instruction->state.swayc_width, .height = instruction->state.swayc_height, }; + // Handle geometry, which may overflow the bounds of the container + struct wlr_box old_surface_box = {0,0,0,0}; + struct wlr_box new_surface_box = {0,0,0,0}; + if (container->type == C_VIEW) { + struct sway_view *view = container->sway_view; + if (container->sway_view->saved_buffer) { + old_surface_box.x = + container->current.view_x - view->saved_geometry.x; + old_surface_box.y = + container->current.view_y - view->saved_geometry.y; + old_surface_box.width = view->saved_buffer_width; + old_surface_box.height = view->saved_buffer_height; + } + struct wlr_surface *surface = container->sway_view->surface; + if (surface) { + struct wlr_box geometry; + view_get_geometry(view, &geometry); + new_surface_box.x = instruction->state.view_x - geometry.x; + new_surface_box.y = instruction->state.view_y - geometry.y; + new_surface_box.width = surface->current.width; + new_surface_box.height = surface->current.height; + } + } for (int j = 0; j < root_container.current.children->length; ++j) { - struct sway_container *output = root_container.current.children->items[j]; + struct sway_container *output = + root_container.current.children->items[j]; if (output->sway_output) { - output_damage_box(output->sway_output, &old_box); - output_damage_box(output->sway_output, &new_box); + output_damage_box(output->sway_output, &old_con_box); + output_damage_box(output->sway_output, &new_con_box); + output_damage_box(output->sway_output, &old_surface_box); + output_damage_box(output->sway_output, &new_surface_box); } } @@ -297,6 +323,7 @@ static void transaction_commit(struct sway_transaction *transaction) { } if (con->type == C_VIEW) { view_save_buffer(con->sway_view); + view_get_geometry(con->sway_view, &con->sway_view->saved_geometry); } con->instruction = instruction; } @@ -355,7 +382,9 @@ static void set_instruction_ready( } instruction->container->instruction = NULL; - transaction_progress_queue(); + if (!txn_debug) { + transaction_progress_queue(); + } } void transaction_notify_view_ready_by_serial(struct sway_view *view, diff --git a/sway/tree/container.c b/sway/tree/container.c index db7802704..1dc4be4b6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -525,6 +525,11 @@ static void surface_at_view(struct sway_container *swayc, double lx, double ly, double view_sx = lx - sview->x; double view_sy = ly - sview->y; + struct wlr_box geometry; + view_get_geometry(sview, &geometry); + view_sx += geometry.x; + view_sy += geometry.y; + double _sx, _sy; struct wlr_surface *_surface = NULL; switch (sview->type) { From 8034c2542620cc9f2699b242cda94c04fee03051 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Fri, 17 Aug 2018 00:03:57 +1000 Subject: [PATCH 3/9] Render saved buffer using saved geometry --- sway/desktop/render.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 93fcfbf49..28c5a3edb 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -234,10 +234,8 @@ static void render_saved_view(struct sway_view *view, .width = view->saved_buffer_width, .height = view->saved_buffer_height, }; - struct wlr_box geometry; - view_get_geometry(view, &geometry); - box.x -= geometry.x; - box.y -= geometry.y; + box.x -= view->saved_geometry.x; + box.y -= view->saved_geometry.y; struct wlr_box output_box = { .width = output->swayc->current.swayc_width, From 9ee89f11c41e723cad8bfb48e1e9b0e743283018 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Fri, 17 Aug 2018 09:25:55 +1000 Subject: [PATCH 4/9] Add get_geometry for xdg_shell_v6 --- sway/desktop/xdg_shell_v6.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 5b3c7b2b1..bbc7456cd 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -106,7 +106,8 @@ static void get_constraints(struct sway_view *view, double *min_width, *max_height = state->max_height > 0 ? state->max_height : DBL_MAX; } -static const char *get_string_prop(struct sway_view *view, enum sway_view_prop prop) { +static const char *get_string_prop(struct sway_view *view, + enum sway_view_prop prop) { if (xdg_shell_v6_view_from_view(view) == NULL) { return NULL; } @@ -120,6 +121,16 @@ static const char *get_string_prop(struct sway_view *view, enum sway_view_prop p } } +static void get_geometry(struct sway_view *view, struct wlr_box *box) { + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + xdg_shell_v6_view_from_view(view); + if (xdg_shell_v6_view == NULL) { + return; + } + struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6; + wlr_xdg_surface_v6_get_geometry(surface, box); +} + static uint32_t configure(struct sway_view *view, double lx, double ly, int width, int height) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = @@ -228,6 +239,7 @@ static void destroy(struct sway_view *view) { static const struct sway_view_impl view_impl = { .get_constraints = get_constraints, .get_string_prop = get_string_prop, + .get_geometry = get_geometry, .configure = configure, .set_activated = set_activated, .set_tiled = set_tiled, From 8af4e2e3e67e4e28e9ffad162984c0cc1414d771 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Fri, 17 Aug 2018 10:23:29 +1000 Subject: [PATCH 5/9] Handle xwayland views sending new sizes in their commits --- sway/desktop/xwayland.c | 12 ++++++++++-- sway/tree/container.c | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index dca62fb1b..b5df907d2 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -282,11 +282,19 @@ static void handle_commit(struct wl_listener *listener, void *data) { wl_container_of(listener, xwayland_view, commit); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - struct wlr_surface_state *surface_state = &xsurface->surface->current; + struct wlr_surface_state *state = &xsurface->surface->current; if (view->swayc->instruction) { transaction_notify_view_ready_by_size(view, - surface_state->width, surface_state->height); + state->width, state->height); + } else if ((state->width != view->width || state->height != view->height) && + container_is_floating(view->swayc)) { + // eg. The Firefox "Save As" dialog when downloading a file + // It maps at a small size then changes afterwards. + view->width = state->width; + view->height = state->height; + container_set_geometry_from_floating_view(view->swayc); + transaction_commit_dirty(); } view_damage_from(view); diff --git a/sway/tree/container.c b/sway/tree/container.c index 1dc4be4b6..b3368a2ed 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1089,6 +1089,7 @@ void container_set_geometry_from_floating_view(struct sway_container *con) { con->y = view->y - top; con->width = view->width + border_width * 2; con->height = top + view->height + border_width; + container_set_dirty(con); } bool container_is_floating(struct sway_container *container) { From 4e755c4b123e1dd8478be63ff6b48d2d1ceaa04b Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Fri, 17 Aug 2018 23:11:09 +1000 Subject: [PATCH 6/9] Set current size when a floating xwayland view resizes This avoids sending an unnecessary configure. --- sway/desktop/xwayland.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index b5df907d2..e0c44b39c 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -293,6 +293,8 @@ static void handle_commit(struct wl_listener *listener, void *data) { // It maps at a small size then changes afterwards. view->width = state->width; view->height = state->height; + view->swayc->current.view_width = state->width; + view->swayc->current.view_height = state->height; container_set_geometry_from_floating_view(view->swayc); transaction_commit_dirty(); } From b0a5f3a25f52bc1d48d771cb02820042006d8d9e Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 18 Aug 2018 15:10:06 +1000 Subject: [PATCH 7/9] Store geometry in the view and handle any floating view resizing --- include/sway/desktop.h | 5 +++ include/sway/tree/view.h | 14 +++++--- sway/desktop/desktop.c | 18 ++++++++++ sway/desktop/output.c | 9 ++--- sway/desktop/render.c | 10 +++--- sway/desktop/transaction.c | 72 ++++++++++++++----------------------- sway/desktop/xdg_shell.c | 28 +++++++++------ sway/desktop/xdg_shell_v6.c | 29 +++++++++------ sway/desktop/xwayland.c | 36 ++++++++++++++----- sway/tree/container.c | 9 ++--- sway/tree/view.c | 26 +++++++------- 11 files changed, 144 insertions(+), 112 deletions(-) diff --git a/include/sway/desktop.h b/include/sway/desktop.h index 348fb1870..c969a76be 100644 --- a/include/sway/desktop.h +++ b/include/sway/desktop.h @@ -1,8 +1,13 @@ #include struct sway_container; +struct sway_view; void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly, bool whole); void desktop_damage_whole_container(struct sway_container *con); + +void desktop_damage_box(struct wlr_box *box); + +void desktop_damage_view(struct sway_view *view); diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 0e7f166cf..2747e7c49 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -38,7 +38,6 @@ struct sway_view_impl { const char *(*get_string_prop)(struct sway_view *view, enum sway_view_prop prop); uint32_t (*get_int_prop)(struct sway_view *view, enum sway_view_prop prop); - void (*get_geometry)(struct sway_view *view, struct wlr_box *box); uint32_t (*configure)(struct sway_view *view, double lx, double ly, int width, int height); void (*set_activated)(struct sway_view *view, bool activated); @@ -88,7 +87,14 @@ struct sway_view { struct wlr_buffer *saved_buffer; int saved_buffer_width, saved_buffer_height; - struct wlr_box saved_geometry; // The "old" geometry during a transaction + + // The geometry for whatever the client is committing, regardless of + // transaction state. Updated on every commit. + struct wlr_box geometry; + + // The "old" geometry during a transaction. Used to damage the old location + // when a transaction is applied. + struct wlr_box saved_geometry; bool destroying; @@ -243,8 +249,6 @@ const char *view_get_shell(struct sway_view *view); void view_get_constraints(struct sway_view *view, double *min_width, double *max_width, double *min_height, double *max_height); -void view_get_geometry(struct sway_view *view, struct wlr_box *box); - uint32_t view_configure(struct sway_view *view, double lx, double ly, int width, int height); @@ -289,6 +293,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); void view_unmap(struct sway_view *view); +void view_update_size(struct sway_view *view, int width, int height); + void view_child_init(struct sway_view_child *child, const struct sway_view_child_impl *impl, struct sway_view *view, struct wlr_surface *surface); diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c index 6575519d4..726503970 100644 --- a/sway/desktop/desktop.c +++ b/sway/desktop/desktop.c @@ -22,3 +22,21 @@ void desktop_damage_whole_container(struct sway_container *con) { } } } + +void desktop_damage_box(struct wlr_box *box) { + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *cont = root_container.children->items[i]; + output_damage_box(cont->sway_output, box); + } +} + +void desktop_damage_view(struct sway_view *view) { + desktop_damage_whole_container(view->swayc); + struct wlr_box box = { + .x = view->swayc->current.view_x - view->geometry.x, + .y = view->swayc->current.view_y - view->geometry.y, + .width = view->surface->current.width, + .height = view->surface->current.height, + }; + desktop_damage_box(&box); +} diff --git a/sway/desktop/output.c b/sway/desktop/output.c index cb0b4a070..b4564faca 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -140,23 +140,20 @@ void output_surface_for_each_surface(struct sway_output *output, void output_view_for_each_surface(struct sway_output *output, struct sway_view *view, sway_surface_iterator_func_t iterator, void *user_data) { - struct wlr_box geometry; - view_get_geometry(view, &geometry); struct surface_iterator_data data = { .user_iterator = iterator, .user_data = user_data, .output = output, .ox = view->swayc->current.view_x - output->swayc->current.swayc_x - - geometry.x, + - view->geometry.x, .oy = view->swayc->current.view_y - output->swayc->current.swayc_y - - geometry.y, + - view->geometry.y, .width = view->swayc->current.view_width, .height = view->swayc->current.view_height, .rotation = 0, // TODO }; - view_for_each_surface(view, - output_for_each_surface_iterator, &data); + view_for_each_surface(view, output_for_each_surface_iterator, &data); } void output_view_for_each_popup(struct sway_output *output, diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 28c5a3edb..a4b624b84 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -192,12 +192,12 @@ static void render_view_toplevels(struct sway_view *view, .damage = damage, .alpha = alpha, }; - struct wlr_box geometry; - view_get_geometry(view, &geometry); // Render all toplevels without descending into popups - output_surface_for_each_surface(output, view->surface, - view->swayc->current.view_x - output->wlr_output->lx - geometry.x, - view->swayc->current.view_y - output->wlr_output->ly - geometry.y, + double ox = + view->swayc->current.view_x - output->wlr_output->lx - view->geometry.x; + double oy = + view->swayc->current.view_y - output->wlr_output->ly - view->geometry.y; + output_surface_for_each_surface(output, view->surface, ox, oy, render_surface_iterator, &data); } diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 7383c4550..c300558ab 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -6,6 +6,7 @@ #include #include #include "sway/debug.h" +#include "sway/desktop.h" #include "sway/desktop/idle_inhibit_v1.h" #include "sway/desktop/transaction.h" #include "sway/output.h" @@ -169,51 +170,17 @@ static void transaction_apply(struct sway_transaction *transaction) { transaction->instructions->items[i]; struct sway_container *container = instruction->container; - // Damage the old and new locations - struct wlr_box old_con_box = { - .x = container->current.swayc_x, - .y = container->current.swayc_y, - .width = container->current.swayc_width, - .height = container->current.swayc_height, - }; - struct wlr_box new_con_box = { - .x = instruction->state.swayc_x, - .y = instruction->state.swayc_y, - .width = instruction->state.swayc_width, - .height = instruction->state.swayc_height, - }; - // Handle geometry, which may overflow the bounds of the container - struct wlr_box old_surface_box = {0,0,0,0}; - struct wlr_box new_surface_box = {0,0,0,0}; - if (container->type == C_VIEW) { + // Damage the old location + desktop_damage_whole_container(container); + if (container->type == C_VIEW && container->sway_view->saved_buffer) { struct sway_view *view = container->sway_view; - if (container->sway_view->saved_buffer) { - old_surface_box.x = - container->current.view_x - view->saved_geometry.x; - old_surface_box.y = - container->current.view_y - view->saved_geometry.y; - old_surface_box.width = view->saved_buffer_width; - old_surface_box.height = view->saved_buffer_height; - } - struct wlr_surface *surface = container->sway_view->surface; - if (surface) { - struct wlr_box geometry; - view_get_geometry(view, &geometry); - new_surface_box.x = instruction->state.view_x - geometry.x; - new_surface_box.y = instruction->state.view_y - geometry.y; - new_surface_box.width = surface->current.width; - new_surface_box.height = surface->current.height; - } - } - for (int j = 0; j < root_container.current.children->length; ++j) { - struct sway_container *output = - root_container.current.children->items[j]; - if (output->sway_output) { - output_damage_box(output->sway_output, &old_con_box); - output_damage_box(output->sway_output, &new_con_box); - output_damage_box(output->sway_output, &old_surface_box); - output_damage_box(output->sway_output, &new_surface_box); - } + struct wlr_box box = { + .x = container->current.view_x - view->saved_geometry.x, + .y = container->current.view_y - view->saved_geometry.y, + .width = view->saved_buffer_width, + .height = view->saved_buffer_height, + }; + desktop_damage_box(&box); } // There are separate children lists for each instruction state, the @@ -230,6 +197,20 @@ static void transaction_apply(struct sway_transaction *transaction) { view_remove_saved_buffer(container->sway_view); } + // Damage the new location + desktop_damage_whole_container(container); + if (container->type == C_VIEW && container->sway_view->surface) { + struct sway_view *view = container->sway_view; + struct wlr_surface *surface = view->surface; + struct wlr_box box = { + .x = container->current.view_x - view->geometry.x, + .y = container->current.view_y - view->geometry.y, + .width = surface->current.width, + .height = surface->current.height, + }; + desktop_damage_box(&box); + } + container->instruction = NULL; } } @@ -323,7 +304,8 @@ static void transaction_commit(struct sway_transaction *transaction) { } if (con->type == C_VIEW) { view_save_buffer(con->sway_view); - view_get_geometry(con->sway_view, &con->sway_view->saved_geometry); + memcpy(&con->sway_view->saved_geometry, &con->sway_view->geometry, + sizeof(struct wlr_box)); } con->instruction = instruction; } diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 2b2603577..aae129bd3 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -7,6 +7,7 @@ #include #include "log.h" #include "sway/decoration.h" +#include "sway/desktop.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/server.h" @@ -122,16 +123,6 @@ static const char *get_string_prop(struct sway_view *view, } } -static void get_geometry(struct sway_view *view, struct wlr_box *box) { - struct sway_xdg_shell_view *xdg_shell_view = - xdg_shell_view_from_view(view); - if (xdg_shell_view == NULL) { - return; - } - struct wlr_xdg_surface *surface = view->wlr_xdg_surface; - wlr_xdg_surface_get_geometry(surface, box); -} - static uint32_t configure(struct sway_view *view, double lx, double ly, int width, int height) { struct sway_xdg_shell_view *xdg_shell_view = @@ -242,7 +233,6 @@ static void destroy(struct sway_view *view) { static const struct sway_view_impl view_impl = { .get_constraints = get_constraints, .get_string_prop = get_string_prop, - .get_geometry = get_geometry, .configure = configure, .set_activated = set_activated, .set_tiled = set_tiled, @@ -267,8 +257,24 @@ static void handle_commit(struct wl_listener *listener, void *data) { } if (view->swayc->instruction) { + wlr_xdg_surface_get_geometry(xdg_surface, &view->geometry); transaction_notify_view_ready_by_serial(view, xdg_surface->configure_serial); + } else { + struct wlr_box new_geo; + wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); + + if ((new_geo.width != view->width || new_geo.height != view->height) && + container_is_floating(view->swayc)) { + // A floating view has unexpectedly sent a new size + desktop_damage_view(view); + view_update_size(view, new_geo.width, new_geo.height); + memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); + desktop_damage_view(view); + transaction_commit_dirty(); + } else { + memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); + } } view_damage_from(view); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index bbc7456cd..277c53a3d 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -6,6 +6,7 @@ #include #include "log.h" #include "sway/decoration.h" +#include "sway/desktop.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/server.h" @@ -121,16 +122,6 @@ static const char *get_string_prop(struct sway_view *view, } } -static void get_geometry(struct sway_view *view, struct wlr_box *box) { - struct sway_xdg_shell_v6_view *xdg_shell_v6_view = - xdg_shell_v6_view_from_view(view); - if (xdg_shell_v6_view == NULL) { - return; - } - struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6; - wlr_xdg_surface_v6_get_geometry(surface, box); -} - static uint32_t configure(struct sway_view *view, double lx, double ly, int width, int height) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = @@ -239,7 +230,6 @@ static void destroy(struct sway_view *view) { static const struct sway_view_impl view_impl = { .get_constraints = get_constraints, .get_string_prop = get_string_prop, - .get_geometry = get_geometry, .configure = configure, .set_activated = set_activated, .set_tiled = set_tiled, @@ -262,9 +252,26 @@ static void handle_commit(struct wl_listener *listener, void *data) { if (!view->swayc) { return; } + if (view->swayc->instruction) { + wlr_xdg_surface_v6_get_geometry(xdg_surface_v6, &view->geometry); transaction_notify_view_ready_by_serial(view, xdg_surface_v6->configure_serial); + } else { + struct wlr_box new_geo; + wlr_xdg_surface_v6_get_geometry(xdg_surface_v6, &new_geo); + + if ((new_geo.width != view->width || new_geo.height != view->height) && + container_is_floating(view->swayc)) { + // A floating view has unexpectedly sent a new size + desktop_damage_view(view); + view_update_size(view, new_geo.width, new_geo.height); + memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); + desktop_damage_view(view); + transaction_commit_dirty(); + } else { + memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); + } } view_damage_from(view); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index e0c44b39c..ce7235e49 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -277,6 +277,17 @@ static const struct sway_view_impl view_impl = { .destroy = destroy, }; +static void get_geometry(struct sway_view *view, struct wlr_box *box) { + box->x = box->y = 0; + if (view->surface) { + box->width = view->surface->current.width; + box->height = view->surface->current.height; + } else { + box->width = 0; + box->height = 0; + } +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, commit); @@ -285,18 +296,25 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct wlr_surface_state *state = &xsurface->surface->current; if (view->swayc->instruction) { + get_geometry(view, &view->geometry); transaction_notify_view_ready_by_size(view, state->width, state->height); - } else if ((state->width != view->width || state->height != view->height) && + } else { + struct wlr_box new_geo; + get_geometry(view, &new_geo); + + if ((new_geo.width != view->width || new_geo.height != view->height) && container_is_floating(view->swayc)) { - // eg. The Firefox "Save As" dialog when downloading a file - // It maps at a small size then changes afterwards. - view->width = state->width; - view->height = state->height; - view->swayc->current.view_width = state->width; - view->swayc->current.view_height = state->height; - container_set_geometry_from_floating_view(view->swayc); - transaction_commit_dirty(); + // A floating view has unexpectedly sent a new size + // eg. The Firefox "Save As" dialog when downloading a file + desktop_damage_view(view); + view_update_size(view, new_geo.width, new_geo.height); + memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); + desktop_damage_view(view); + transaction_commit_dirty(); + } else { + memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); + } } view_damage_from(view); diff --git a/sway/tree/container.c b/sway/tree/container.c index b3368a2ed..b3f3a3440 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -522,13 +522,8 @@ static void surface_at_view(struct sway_container *swayc, double lx, double ly, return; } struct sway_view *sview = swayc->sway_view; - double view_sx = lx - sview->x; - double view_sy = ly - sview->y; - - struct wlr_box geometry; - view_get_geometry(sview, &geometry); - view_sx += geometry.x; - view_sy += geometry.y; + double view_sx = lx - sview->x + sview->geometry.x; + double view_sy = ly - sview->y + sview->geometry.y; double _sx, _sy; struct wlr_surface *_surface = NULL; diff --git a/sway/tree/view.c b/sway/tree/view.c index fba0b52d3..fbe4bc582 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -162,20 +162,6 @@ void view_get_constraints(struct sway_view *view, double *min_width, } } -void view_get_geometry(struct sway_view *view, struct wlr_box *box) { - if (view->surface == NULL) { - box->x = box->y = box->width = box->height = 0; - return; - } - if (view->impl->get_geometry) { - view->impl->get_geometry(view, box); - return; - } - box->x = box->y = 0; - box->width = view->surface->current.width; - box->height = view->surface->current.height; -} - uint32_t view_configure(struct sway_view *view, double lx, double ly, int width, int height) { if (view->impl->configure) { @@ -629,6 +615,18 @@ void view_unmap(struct sway_view *view) { view->surface = NULL; } +void view_update_size(struct sway_view *view, int width, int height) { + if (!sway_assert(container_is_floating(view->swayc), + "Expected a floating container")) { + return; + } + view->width = width; + view->height = height; + view->swayc->current.view_width = width; + view->swayc->current.view_height = height; + container_set_geometry_from_floating_view(view->swayc); +} + static void view_subsurface_create(struct sway_view *view, struct wlr_subsurface *subsurface) { struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child)); From ce78f6770e9c950d5335bedfd123979428561ae1 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 18 Aug 2018 15:11:46 +1000 Subject: [PATCH 8/9] Fix nitpick --- sway/desktop/render.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index a4b624b84..7c48d0d27 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -229,13 +229,13 @@ static void render_saved_view(struct sway_view *view, return; } struct wlr_box box = { - .x = view->swayc->current.view_x - output->swayc->current.swayc_x, - .y = view->swayc->current.view_y - output->swayc->current.swayc_y, + .x = view->swayc->current.view_x - output->swayc->current.swayc_x - + view->saved_geometry.x, + .y = view->swayc->current.view_y - output->swayc->current.swayc_y - + view->saved_geometry.y, .width = view->saved_buffer_width, .height = view->saved_buffer_height, }; - box.x -= view->saved_geometry.x; - box.y -= view->saved_geometry.y; struct wlr_box output_box = { .width = output->swayc->current.swayc_width, From 1be75fe7403fd64e084008b0ed677fa4df32ed5b Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sat, 18 Aug 2018 18:10:41 +0100 Subject: [PATCH 9/9] Fix double iterating in container_for_each_child --- sway/tree/container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 1ceae1755..9bc4f5441 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -737,10 +737,10 @@ void container_for_each_child(struct sway_container *container, container->type == C_VIEW, "Expected a container or view")) { return; } - f(container, data); if (container->children) { for (int i = 0; i < container->children->length; ++i) { struct sway_container *child = container->children->items[i]; + f(child, data); container_for_each_child(child, f, data); } }