From de86d65627e96cffe77f4abf11c4a0b982326ff9 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 31 Jul 2018 18:41:30 +1000 Subject: [PATCH 01/24] Fix popups Fixes the render and container_at order for popups. Fixes #2210 For rendering: * render_view_surfaces has been renamed to render_view_toplevels * render_view_toplevels now uses output_surface_for_each_surface (which is now public), as that function uses wlr_surface_for_each_surface which doesn't descend into popups * Views now have a for_each_popup iterator, which is used by the renderer to render the focused view's popups * When rendering a popup, toplevels (xdg subsurfaces) of that popup are also rendered For sending frame done, the logic has been updated to match the rendering logic: * send_frame_done_container no longer descends into popups * for_each_popup is used to send frame done to the focused view's popups and their child toplevels For container_at: * floating_container_at is now static, which means it had to be moved higher in the file. * container_at now considers popups for the focused view before checking containers. * tiling_container_at has been introduced, so that it doesn't call container_at recursively (it would check popups recursively if it did) --- include/sway/output.h | 8 ++ include/sway/tree/container.h | 11 +-- include/sway/tree/view.h | 11 +++ sway/desktop/output.c | 52 ++++++++++++- sway/desktop/render.c | 37 +++++++++- sway/desktop/xdg_shell.c | 9 +++ sway/desktop/xdg_shell_v6.c | 10 +++ sway/input/cursor.c | 3 - sway/tree/container.c | 134 ++++++++++++++++++++++++---------- sway/tree/view.c | 10 +++ 10 files changed, 228 insertions(+), 57 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 6283db68a..80dcd37b0 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -67,10 +67,18 @@ struct sway_container *output_get_active_workspace(struct sway_output *output); void output_render(struct sway_output *output, struct timespec *when, pixman_region32_t *damage); +void output_surface_for_each_surface(struct sway_output *output, + struct wlr_surface *surface, double ox, double oy, + sway_surface_iterator_func_t iterator, void *user_data); + void output_view_for_each_surface(struct sway_output *output, struct sway_view *view, sway_surface_iterator_func_t iterator, void *user_data); +void output_view_for_each_popup(struct sway_output *output, + struct sway_view *view, sway_surface_iterator_func_t iterator, + void *user_data); + void output_layer_for_each_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data); diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index d4a42a718..12ff8a5a7 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -230,17 +230,10 @@ struct sway_container *container_parent(struct sway_container *container, * surface-local coordinates of the given layout coordinates if the container * is a view and the view contains a surface at those coordinates. */ -struct sway_container *container_at(struct sway_container *container, - double ox, double oy, struct wlr_surface **surface, +struct sway_container *container_at(struct sway_container *workspace, + double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); -/** - * Same as container_at, but only checks floating views and expects coordinates - * to be layout coordinates, as that's what floating views use. - */ -struct sway_container *floating_container_at(double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy); - /** * Apply the function for each descendant of the container breadth first. */ diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 0152ed554..9f6d36fe3 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -47,6 +47,8 @@ struct sway_view_impl { bool (*has_client_side_decorations)(struct sway_view *view); void (*for_each_surface)(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); + void (*for_each_popup)(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data); void (*close)(struct sway_view *view); void (*destroy)(struct sway_view *view); }; @@ -248,9 +250,18 @@ void view_close(struct sway_view *view); void view_damage_from(struct sway_view *view); +/** + * Iterate all surfaces of a view (toplevels + popups). + */ void view_for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); +/** + * Iterate all popups recursively. + */ +void view_for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data); + // view implementation void view_init(struct sway_view *view, enum sway_view_type type, diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 31b532135..4c9d978c9 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -119,7 +119,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface, data->user_data); } -static void output_surface_for_each_surface(struct sway_output *output, +void output_surface_for_each_surface(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, sway_surface_iterator_func_t iterator, void *user_data) { struct surface_iterator_data data = { @@ -155,6 +155,23 @@ void output_view_for_each_surface(struct sway_output *output, output_for_each_surface_iterator, &data); } +void output_view_for_each_popup(struct sway_output *output, + struct sway_view *view, sway_surface_iterator_func_t iterator, + void *user_data) { + 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, + .width = view->swayc->current.view_width, + .height = view->swayc->current.view_height, + .rotation = 0, // TODO + }; + + view_for_each_popup(view, output_for_each_surface_iterator, &data); +} + void output_layer_for_each_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data) { @@ -295,8 +312,9 @@ static void send_frame_done_container_iterator(struct sway_container *con, return; } - output_view_for_each_surface(data->output, con->sway_view, - send_frame_done_iterator, data->when); + // Toplevels only + output_surface_for_each_surface(data->output, con->sway_view->surface, + con->x, con->y, send_frame_done_iterator, data->when); } static void send_frame_done_container(struct sway_output *output, @@ -309,6 +327,27 @@ static void send_frame_done_container(struct sway_output *output, send_frame_done_container_iterator, &data); } +static void send_frame_done_popup_iterator(struct sway_output *output, + struct wlr_surface *surface, struct wlr_box *box, float rotation, + void *data) { + // Send frame done to this popup's surface + send_frame_done_iterator(output, surface, box, rotation, data); + + // Send frame done to this popup's child toplevels + output_surface_for_each_surface(output, surface, box->x, box->y, + send_frame_done_iterator, data); +} + +static void send_frame_done_popups(struct sway_output *output, + struct sway_view *view, struct timespec *when) { + struct send_frame_done_data data = { + .output = output, + .when = when, + }; + output_view_for_each_popup(output, view, + send_frame_done_popup_iterator, &data); +} + static void send_frame_done(struct sway_output *output, struct timespec *when) { if (output_has_opaque_overlay_layer_surface(output)) { goto send_frame_overlay; @@ -346,6 +385,13 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when); } + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = seat_get_focus(seat); + if (focus && focus->type == C_VIEW) { + send_frame_done_popups(output, focus->sway_view, when); + } + + send_frame_overlay: send_frame_done_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index f25055b81..ea4361f23 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -186,13 +186,36 @@ static void premultiply_alpha(float color[4], float opacity) { color[2] *= color[3]; } -static void render_view_surfaces(struct sway_view *view, +static void render_view_toplevels(struct sway_view *view, struct sway_output *output, pixman_region32_t *damage, float alpha) { struct render_data data = { .damage = damage, .alpha = alpha, }; - output_view_for_each_surface(output, view, render_surface_iterator, &data); + // Render all toplevels without descending into popups + output_surface_for_each_surface(output, view->surface, + view->swayc->current.view_x, view->swayc->current.view_y, + render_surface_iterator, &data); +} + +static void render_popup_iterator(struct sway_output *output, + struct wlr_surface *surface, struct wlr_box *box, float rotation, + void *data) { + // Render this popup's surface + render_surface_iterator(output, surface, box, rotation, data); + + // Render this popup's child toplevels + output_surface_for_each_surface(output, surface, box->x, box->y, + render_surface_iterator, data); +} + +static void render_view_popups(struct sway_view *view, + struct sway_output *output, pixman_region32_t *damage, float alpha) { + struct render_data data = { + .damage = damage, + .alpha = alpha, + }; + output_view_for_each_popup(output, view, render_popup_iterator, &data); } static void render_saved_view(struct sway_view *view, @@ -241,7 +264,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, if (view->swayc->instructions->length) { render_saved_view(view, output, damage, view->swayc->alpha); } else { - render_view_surfaces(view, output, damage, view->swayc->alpha); + render_view_toplevels(view, output, damage, view->swayc->alpha); } if (view->using_csd) { @@ -845,7 +868,7 @@ void output_render(struct sway_output *output, struct timespec *when, render_saved_view(fullscreen_con->sway_view, output, damage, 1.0f); } else { - render_view_surfaces(fullscreen_con->sway_view, + render_view_toplevels(fullscreen_con->sway_view, output, damage, 1.0f); } } else { @@ -881,6 +904,12 @@ void output_render(struct sway_output *output, struct timespec *when, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = seat_get_focus(seat); + if (focus && focus->type == C_VIEW) { + render_view_popups(focus->sway_view, output, damage, focus->alpha); + } + render_overlay: render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index e6e1527e7..9f94bd74a 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -179,6 +179,14 @@ static void for_each_surface(struct sway_view *view, user_data); } +static void for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (xdg_shell_view_from_view(view) == NULL) { + return; + } + wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data); +} + static void _close(struct sway_view *view) { if (xdg_shell_view_from_view(view) == NULL) { return; @@ -207,6 +215,7 @@ static const struct sway_view_impl view_impl = { .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, .for_each_surface = for_each_surface, + .for_each_popup = for_each_popup, .close = _close, .destroy = destroy, }; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 5feee3e4c..4502c3860 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -175,6 +175,15 @@ static void for_each_surface(struct sway_view *view, user_data); } +static void for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (xdg_shell_v6_view_from_view(view) == NULL) { + return; + } + wlr_xdg_surface_v6_for_each_popup(view->wlr_xdg_surface_v6, iterator, + user_data); +} + static void _close(struct sway_view *view) { if (xdg_shell_v6_view_from_view(view) == NULL) { return; @@ -203,6 +212,7 @@ static const struct sway_view_impl view_impl = { .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, .for_each_surface = for_each_surface, + .for_each_popup = for_each_popup, .close = _close, .destroy = destroy, }; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 96ac7b330..ad4b1718b 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -109,9 +109,6 @@ static struct sway_container *container_at_coords( } struct sway_container *c; - if ((c = floating_container_at(lx, ly, surface, sx, sy))) { - return c; - } if ((c = container_at(ws, lx, ly, surface, sx, sy))) { return c; } diff --git a/sway/tree/container.c b/sway/tree/container.c index 4e85021de..b5fefd172 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -561,10 +561,15 @@ static struct sway_container *container_at_view(struct sway_container *swayc, *sx = _sx; *sy = _sy; *surface = _surface; + return swayc; } - return swayc; + return NULL; } +static struct sway_container *tiling_container_at( + struct sway_container *con, double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy); + /** * container_at for a container with layout L_TABBED. */ @@ -591,7 +596,7 @@ static struct sway_container *container_at_tabbed(struct sway_container *parent, // Surfaces struct sway_container *current = seat_get_active_child(seat, parent); - return container_at(current, lx, ly, surface, sx, sy); + return tiling_container_at(current, lx, ly, surface, sx, sy); } /** @@ -616,7 +621,7 @@ static struct sway_container *container_at_stacked( // Surfaces struct sway_container *current = seat_get_active_child(seat, parent); - return container_at(current, lx, ly, surface, sx, sy); + return tiling_container_at(current, lx, ly, surface, sx, sy); } /** @@ -634,45 +639,13 @@ static struct sway_container *container_at_linear(struct sway_container *parent, .height = child->height, }; if (wlr_box_contains_point(&box, lx, ly)) { - return container_at(child, lx, ly, surface, sx, sy); + return tiling_container_at(child, lx, ly, surface, sx, sy); } } return NULL; } -struct sway_container *container_at(struct sway_container *parent, - double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy) { - if (!sway_assert(parent->type >= C_WORKSPACE, - "Expected workspace or deeper")) { - return NULL; - } - if (parent->type == C_VIEW) { - return container_at_view(parent, lx, ly, surface, sx, sy); - } - if (!parent->children->length) { - return NULL; - } - - switch (parent->layout) { - case L_HORIZ: - case L_VERT: - return container_at_linear(parent, lx, ly, surface, sx, sy); - case L_TABBED: - return container_at_tabbed(parent, lx, ly, surface, sx, sy); - case L_STACKED: - return container_at_stacked(parent, lx, ly, surface, sx, sy); - case L_FLOATING: - sway_assert(false, "Didn't expect to see floating here"); - return NULL; - case L_NONE: - return NULL; - } - - return NULL; -} - -struct sway_container *floating_container_at(double lx, double ly, +static struct sway_container *floating_container_at(double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *output = root_container.children->items[i]; @@ -694,7 +667,8 @@ struct sway_container *floating_container_at(double lx, double ly, .height = floater->height, }; if (wlr_box_contains_point(&box, lx, ly)) { - return container_at(floater, lx, ly, surface, sx, sy); + return tiling_container_at(floater, lx, ly, + surface, sx, sy); } } } @@ -702,6 +676,90 @@ struct sway_container *floating_container_at(double lx, double ly, return NULL; } +static struct sway_container *tiling_container_at( + struct sway_container *con, double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy) { + if (con->type == C_VIEW) { + return container_at_view(con, lx, ly, surface, sx, sy); + } + if (!con->children->length) { + return NULL; + } + + switch (con->layout) { + case L_HORIZ: + case L_VERT: + return container_at_linear(con, lx, ly, surface, sx, sy); + case L_TABBED: + return container_at_tabbed(con, lx, ly, surface, sx, sy); + case L_STACKED: + return container_at_stacked(con, lx, ly, surface, sx, sy); + case L_FLOATING: + sway_assert(false, "Didn't expect to see floating here"); + return NULL; + case L_NONE: + return NULL; + } + return NULL; +} + +static bool surface_is_popup(struct wlr_surface *surface) { + if (wlr_surface_is_xdg_surface(surface)) { + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(surface); + while (xdg_surface) { + if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { + return true; + } + xdg_surface = xdg_surface->toplevel->parent; + } + return false; + } + + if (wlr_surface_is_xdg_surface_v6(surface)) { + struct wlr_xdg_surface_v6 *xdg_surface_v6 = + wlr_xdg_surface_v6_from_wlr_surface(surface); + while (xdg_surface_v6) { + if (xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { + return true; + } + xdg_surface_v6 = xdg_surface_v6->toplevel->parent; + } + return false; + } + + return false; +} + +struct sway_container *container_at(struct sway_container *workspace, + double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy) { + if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) { + return NULL; + } + struct sway_container *c; + // Focused view's popups + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = + seat_get_focus_inactive(seat, &root_container); + if (focus && focus->type == C_VIEW) { + container_at_view(focus, lx, ly, surface, sx, sy); + if (*surface && surface_is_popup(*surface)) { + return focus; + } + *surface = NULL; + } + // Floating + if ((c = floating_container_at(lx, ly, surface, sx, sy))) { + return c; + } + // Tiling + if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) { + return c; + } + return NULL; +} + void container_for_each_descendant_dfs(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 8f54cc119..c12078214 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -332,6 +332,16 @@ void view_for_each_surface(struct sway_view *view, } } +void view_for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (!view->surface) { + return; + } + if (view->impl->for_each_popup) { + view->impl->for_each_popup(view, iterator, user_data); + } +} + static void view_subsurface_create(struct sway_view *view, struct wlr_subsurface *subsurface); From 7a59508da467a3b793e355e28ae67ce04633761c Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 31 Jul 2018 19:58:34 +1000 Subject: [PATCH 02/24] Close popups when changing focus Also reverts the send frame done changes from the previous commit. --- include/sway/tree/view.h | 3 +++ sway/desktop/output.c | 33 ++------------------------------- sway/desktop/xdg_shell.c | 13 +++++++++++++ sway/desktop/xdg_shell_v6.c | 13 +++++++++++++ sway/input/seat.c | 7 +++++++ sway/tree/view.c | 6 ++++++ 6 files changed, 44 insertions(+), 31 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 9f6d36fe3..e722ca5e7 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -50,6 +50,7 @@ struct sway_view_impl { void (*for_each_popup)(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); void (*close)(struct sway_view *view); + void (*close_popups)(struct sway_view *view); void (*destroy)(struct sway_view *view); }; @@ -248,6 +249,8 @@ void view_set_tiled(struct sway_view *view, bool tiled); void view_close(struct sway_view *view); +void view_close_popups(struct sway_view *view); + void view_damage_from(struct sway_view *view); /** diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 4c9d978c9..66747a3f8 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -312,9 +312,8 @@ static void send_frame_done_container_iterator(struct sway_container *con, return; } - // Toplevels only - output_surface_for_each_surface(data->output, con->sway_view->surface, - con->x, con->y, send_frame_done_iterator, data->when); + output_view_for_each_surface(data->output, con->sway_view, + send_frame_done_iterator, data->when); } static void send_frame_done_container(struct sway_output *output, @@ -327,27 +326,6 @@ static void send_frame_done_container(struct sway_output *output, send_frame_done_container_iterator, &data); } -static void send_frame_done_popup_iterator(struct sway_output *output, - struct wlr_surface *surface, struct wlr_box *box, float rotation, - void *data) { - // Send frame done to this popup's surface - send_frame_done_iterator(output, surface, box, rotation, data); - - // Send frame done to this popup's child toplevels - output_surface_for_each_surface(output, surface, box->x, box->y, - send_frame_done_iterator, data); -} - -static void send_frame_done_popups(struct sway_output *output, - struct sway_view *view, struct timespec *when) { - struct send_frame_done_data data = { - .output = output, - .when = when, - }; - output_view_for_each_popup(output, view, - send_frame_done_popup_iterator, &data); -} - static void send_frame_done(struct sway_output *output, struct timespec *when) { if (output_has_opaque_overlay_layer_surface(output)) { goto send_frame_overlay; @@ -385,13 +363,6 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when); } - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); - if (focus && focus->type == C_VIEW) { - send_frame_done_popups(output, focus->sway_view, when); - } - - send_frame_overlay: send_frame_done_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 9f94bd74a..b364663d8 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -197,6 +197,18 @@ static void _close(struct sway_view *view) { } } +static void close_popups_iterator(struct wlr_surface *surface, + int sx, int sy, void *data) { + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(surface); + wlr_xdg_surface_send_close(xdg_surface); +} + +static void close_popups(struct sway_view *view) { + wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, + close_popups_iterator, NULL); +} + static void destroy(struct sway_view *view) { struct sway_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); @@ -217,6 +229,7 @@ static const struct sway_view_impl view_impl = { .for_each_surface = for_each_surface, .for_each_popup = for_each_popup, .close = _close, + .close_popups = close_popups, .destroy = destroy, }; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 4502c3860..ffea03ad2 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -194,6 +194,18 @@ static void _close(struct sway_view *view) { } } +static void close_popups_iterator(struct wlr_surface *surface, + int sx, int sy, void *data) { + struct wlr_xdg_surface_v6 *xdg_surface_v6 = + wlr_xdg_surface_v6_from_wlr_surface(surface); + wlr_xdg_surface_v6_send_close(xdg_surface_v6); +} + +static void close_popups(struct sway_view *view) { + wlr_xdg_surface_v6_for_each_popup(view->wlr_xdg_surface_v6, + close_popups_iterator, NULL); +} + static void destroy(struct sway_view *view) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = xdg_shell_v6_view_from_view(view); @@ -214,6 +226,7 @@ static const struct sway_view_impl view_impl = { .for_each_surface = for_each_surface, .for_each_popup = for_each_popup, .close = _close, + .close_popups = close_popups, .destroy = destroy, }; diff --git a/sway/input/seat.c b/sway/input/seat.c index 53a929895..8ed0dce20 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -737,6 +737,13 @@ void seat_set_focus_warp(struct sway_seat *seat, } } + // Close any popups on the old focus + if (last_focus && last_focus != container) { + if (last_focus->type == C_VIEW) { + view_close_popups(last_focus->sway_view); + } + } + if (last_focus) { if (last_workspace) { ipc_event_workspace(last_workspace, container, "focus"); diff --git a/sway/tree/view.c b/sway/tree/view.c index c12078214..5d9b625f6 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -302,6 +302,12 @@ void view_close(struct sway_view *view) { } } +void view_close_popups(struct sway_view *view) { + if (view->impl->close_popups) { + view->impl->close_popups(view); + } +} + void view_damage_from(struct sway_view *view) { for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *cont = root_container.children->items[i]; From 00a00aacef7e9995d4cd1177ce1258a96f56d5c9 Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Tue, 31 Jul 2018 23:49:42 -0400 Subject: [PATCH 03/24] Create list for mouse binds when creating new mode --- sway/commands/mode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/commands/mode.c b/sway/commands/mode.c index b460fcb5a..637ca45ec 100644 --- a/sway/commands/mode.c +++ b/sway/commands/mode.c @@ -56,6 +56,7 @@ struct cmd_results *cmd_mode(int argc, char **argv) { mode->name = strdup(mode_name); mode->keysym_bindings = create_list(); mode->keycode_bindings = create_list(); + mode->mouse_bindings = create_list(); mode->pango = pango; list_add(config->modes, mode); } From d10ccc1eb144e4de2477398f6b11753f6b7df70b Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 1 Aug 2018 16:23:11 +1000 Subject: [PATCH 04/24] Correctly track saved surfaces during multiple transactions Fixes #2364. Suppose a view is 600px wide, and we tell it to resize to 601px during a resize operation. We create a transaction, save the 600px buffer and send the configure. This buffer is saved into the associated instruction, and is rendered while we wait for the view to commit a 601px buffer. Before the view commits the 601px buffer, suppose we tell it to resize to 602px. The new transaction will also save the buffer, but it's still the 600px buffer because we haven't received a new one yet. Then suppose the view commits its original 601px buffer. This completes the first transaction, so we apply the 601px width to the container. There's still the second (now only) transaction remaining, so we render the saved buffer from that. But this is still the 600px buffer, and we believe it's 601px. Whoops. The problem here is we can't stack buffers like this. So this commit removes the saved buffer from the instructions, places it in the view instead, and re-saves the latest buffer every time the view completes a transaction and still has further pending transactions. As saved buffers are now specific to views rather than instructions, the functions for saving and removing the saved buffer have been moved to view.c. The calls to save and restore the buffer have been relocated to more appropriate functions too, favouring transaction_commit and transaction_apply rather than transaction_add_container and transaction_destroy. --- include/sway/desktop/transaction.h | 13 -------- include/sway/tree/view.h | 7 ++++ sway/desktop/render.c | 16 ++++------ sway/desktop/transaction.c | 51 +++++++----------------------- sway/tree/view.c | 20 ++++++++++++ 5 files changed, 46 insertions(+), 61 deletions(-) diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h index cee4afed6..56361d944 100644 --- a/include/sway/desktop/transaction.h +++ b/include/sway/desktop/transaction.h @@ -42,17 +42,4 @@ void transaction_notify_view_ready(struct sway_view *view, uint32_t serial); void transaction_notify_view_ready_by_size(struct sway_view *view, int width, int height); -/** - * Get the saved texture that should be rendered for a view. - * - * The addresses pointed at by the width and height pointers will be populated - * with the surface's dimensions, which may be different to the texture's - * dimensions if output scaling is used. - * - * This function should only be called if it is known that the view has - * instructions. - */ -struct wlr_texture *transaction_get_saved_texture(struct sway_view *view, - int *width, int *height); - #endif diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 0152ed554..0f9b0bb2f 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -82,6 +82,9 @@ struct sway_view { bool allow_request_urgent; struct wl_event_source *urgent_timer; + struct wlr_buffer *saved_buffer; + int saved_buffer_width, saved_buffer_height; + bool destroying; list_t *executed_criteria; // struct criteria * @@ -323,4 +326,8 @@ void view_set_urgent(struct sway_view *view, bool enable); bool view_is_urgent(struct sway_view *view); +void view_remove_saved_buffer(struct sway_view *view); + +void view_save_buffer(struct sway_view *view); + #endif diff --git a/sway/desktop/render.c b/sway/desktop/render.c index f25055b81..f0e47c958 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -199,17 +199,14 @@ static void render_saved_view(struct sway_view *view, struct sway_output *output, pixman_region32_t *damage, float alpha) { struct wlr_output *wlr_output = output->wlr_output; - int width, height; - struct wlr_texture *texture = - transaction_get_saved_texture(view, &width, &height); - if (!texture) { + if (!view->saved_buffer || !view->saved_buffer->texture) { 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, - .width = width, - .height = height, + .width = view->saved_buffer_width, + .height = view->saved_buffer_height, }; struct wlr_box output_box = { @@ -229,7 +226,8 @@ static void render_saved_view(struct sway_view *view, wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, wlr_output->transform_matrix); - render_texture(wlr_output, damage, texture, &box, matrix, alpha); + render_texture(wlr_output, damage, view->saved_buffer->texture, + &box, matrix, alpha); } /** @@ -238,7 +236,7 @@ static void render_saved_view(struct sway_view *view, static void render_view(struct sway_output *output, pixman_region32_t *damage, struct sway_container *con, struct border_colors *colors) { struct sway_view *view = con->sway_view; - if (view->swayc->instructions->length) { + if (view->saved_buffer) { render_saved_view(view, output, damage, view->swayc->alpha); } else { render_view_surfaces(view, output, damage, view->swayc->alpha); @@ -841,7 +839,7 @@ void output_render(struct sway_output *output, struct timespec *when, // TODO: handle views smaller than the output if (fullscreen_con->type == C_VIEW) { - if (fullscreen_con->instructions->length) { + if (fullscreen_con->sway_view->saved_buffer) { render_saved_view(fullscreen_con->sway_view, output, damage, 1.0f); } else { diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 7975366e6..94070363f 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -41,8 +41,6 @@ struct sway_transaction_instruction { struct sway_transaction *transaction; struct sway_container *container; struct sway_container_state state; - struct wlr_buffer *saved_buffer; - int saved_buffer_width, saved_buffer_height; uint32_t serial; bool ready; }; @@ -57,27 +55,6 @@ static struct sway_transaction *transaction_create() { return transaction; } -static void remove_saved_view_buffer( - struct sway_transaction_instruction *instruction) { - if (instruction->saved_buffer) { - wlr_buffer_unref(instruction->saved_buffer); - instruction->saved_buffer = NULL; - } -} - -static void save_view_buffer(struct sway_view *view, - struct sway_transaction_instruction *instruction) { - if (!sway_assert(instruction->saved_buffer == NULL, - "Didn't expect instruction to have a saved buffer already")) { - remove_saved_view_buffer(instruction); - } - if (view->surface && wlr_surface_has_buffer(view->surface)) { - instruction->saved_buffer = wlr_buffer_ref(view->surface->buffer); - instruction->saved_buffer_width = view->surface->current.width; - instruction->saved_buffer_height = view->surface->current.height; - } -} - static void transaction_destroy(struct sway_transaction *transaction) { // Free instructions for (int i = 0; i < transaction->instructions->length; ++i) { @@ -93,7 +70,6 @@ static void transaction_destroy(struct sway_transaction *transaction) { if (con->destroying && !con->instructions->length) { container_free(con); } - remove_saved_view_buffer(instruction); free(instruction); } list_free(transaction->instructions); @@ -158,9 +134,6 @@ static void transaction_add_container(struct sway_transaction *transaction, copy_pending_state(container, &instruction->state); - if (container->type == C_VIEW) { - save_view_buffer(container->sway_view, instruction); - } list_add(transaction->instructions, instruction); } @@ -220,6 +193,15 @@ static void transaction_apply(struct sway_transaction *transaction) { memcpy(&container->current, &instruction->state, sizeof(struct sway_container_state)); + + if (container->type == C_VIEW) { + if (container->sway_view->saved_buffer) { + view_remove_saved_buffer(container->sway_view); + } + if (container->instructions->length > 1) { + view_save_buffer(container->sway_view); + } + } } } @@ -294,6 +276,9 @@ static void transaction_commit(struct sway_transaction *transaction) { // mapping and its default geometry doesn't intersect an output. struct timespec when; wlr_surface_send_frame_done(con->sway_view->surface, &when); + if (!con->sway_view->saved_buffer) { + view_save_buffer(con->sway_view); + } } list_add(con->instructions, instruction); } @@ -400,18 +385,6 @@ void transaction_notify_view_ready_by_size(struct sway_view *view, } } -struct wlr_texture *transaction_get_saved_texture(struct sway_view *view, - int *width, int *height) { - struct sway_transaction_instruction *instruction = - view->swayc->instructions->items[0]; - if (!instruction->saved_buffer) { - return NULL; - } - *width = instruction->saved_buffer_width; - *height = instruction->saved_buffer_height; - return instruction->saved_buffer->texture; -} - void transaction_commit_dirty(void) { if (!server.dirty_containers->length) { return; diff --git a/sway/tree/view.c b/sway/tree/view.c index 8f54cc119..0dbd3812d 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "config.h" #ifdef HAVE_XWAYLAND @@ -1070,3 +1071,22 @@ void view_set_urgent(struct sway_view *view, bool enable) { bool view_is_urgent(struct sway_view *view) { return view->urgent.tv_sec || view->urgent.tv_nsec; } + +void view_remove_saved_buffer(struct sway_view *view) { + if (!sway_assert(view->saved_buffer, "Expected a saved buffer")) { + return; + } + wlr_buffer_unref(view->saved_buffer); + view->saved_buffer = NULL; +} + +void view_save_buffer(struct sway_view *view) { + if (!sway_assert(!view->saved_buffer, "Didn't expect saved buffer")) { + view_remove_saved_buffer(view); + } + if (view->surface && wlr_surface_has_buffer(view->surface)) { + view->saved_buffer = wlr_buffer_ref(view->surface->buffer); + view->saved_buffer_width = view->surface->current.width; + view->saved_buffer_height = view->surface->current.height; + } +} From 77d74dd34fd7126d6159234c883b50a5a021e24a Mon Sep 17 00:00:00 2001 From: chr0me Date: Wed, 1 Aug 2018 19:48:43 +0800 Subject: [PATCH 05/24] XCursor is not configured if no pointer device is available --- sway/input/seat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 53a929895..a4a449e49 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -393,7 +393,6 @@ struct sway_seat *seat_create(struct sway_input_manager *input, WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_TOUCH); - seat_configure_xcursor(seat); wl_list_insert(&input->seats, &seat->link); @@ -438,6 +437,7 @@ static void seat_apply_input_config(struct sway_seat *seat, static void seat_configure_pointer(struct sway_seat *seat, struct sway_seat_device *sway_device) { + seat_configure_xcursor(seat); wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); seat_apply_input_config(seat, sway_device); From e8b179e313632c150ff7775f4f740296465cb58a Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 13 Jul 2018 16:58:45 +0100 Subject: [PATCH 06/24] ipc: add shutdown event --- include/ipc.h | 5 +++-- include/sway/ipc-server.h | 1 + sway/ipc-server.c | 16 ++++++++++++++++ sway/main.c | 1 + 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/ipc.h b/include/ipc.h index 0010718bd..ffc57d1be 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -27,8 +27,9 @@ enum ipc_command_type { IPC_EVENT_WINDOW = ((1<<31) | 3), IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4), IPC_EVENT_BINDING = ((1<<31) | 5), - IPC_EVENT_MODIFIER = ((1<<31) | 6), - IPC_EVENT_INPUT = ((1<<31) | 7), + IPC_EVENT_SHUTDOWN = ((1<<31) | 6), + IPC_EVENT_MODIFIER = ((1<<31) | 16), + IPC_EVENT_INPUT = ((1<<31) | 17), }; #endif diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index 6469f097c..a11735cfe 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -16,5 +16,6 @@ void ipc_event_workspace(struct sway_container *old, void ipc_event_window(struct sway_container *window, const char *change); void ipc_event_barconfig_update(struct bar_config *bar); void ipc_event_mode(const char *mode, bool pango); +void ipc_event_shutdown(const char *reason); #endif diff --git a/sway/ipc-server.c b/sway/ipc-server.c index be7039152..72031e243 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -353,6 +353,20 @@ void ipc_event_mode(const char *mode, bool pango) { json_object_put(obj); } +void ipc_event_shutdown(const char *reason) { + if (!ipc_has_event_listeners(IPC_EVENT_SHUTDOWN)) { + return; + } + wlr_log(WLR_DEBUG, "Sending shutdown::%s event", reason); + + json_object *json = json_object_new_object(); + json_object_object_add(json, "change", json_object_new_string(reason)); + + const char *json_string = json_object_to_json_string(json); + ipc_send_event(json_string, IPC_EVENT_SHUTDOWN); + json_object_put(json); +} + int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; @@ -549,6 +563,8 @@ void ipc_client_handle_command(struct ipc_client *client) { client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE); } else if (strcmp(event_type, "mode") == 0) { client->subscribed_events |= event_mask(IPC_EVENT_MODE); + } else if (strcmp(event_type, "shutdown") == 0) { + client->subscribed_events |= event_mask(IPC_EVENT_SHUTDOWN); } else if (strcmp(event_type, "window") == 0) { client->subscribed_events |= event_mask(IPC_EVENT_WINDOW); } else if (strcmp(event_type, "modifier") == 0) { diff --git a/sway/main.c b/sway/main.c index a20f1dacb..477ffa5a2 100644 --- a/sway/main.c +++ b/sway/main.c @@ -36,6 +36,7 @@ struct sway_server server; void sway_terminate(int exit_code) { terminate_request = true; exit_value = exit_code; + ipc_event_shutdown("exit"); wl_display_terminate(server.wl_display); } From 87ccf189646cfc79db791ef9b81b5b3f0c2040b7 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 13 Jul 2018 17:13:25 +0100 Subject: [PATCH 07/24] ipc: add workspace::init event --- sway/tree/container.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index 4e85021de..f082e8b1d 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -64,6 +64,8 @@ void container_create_notify(struct sway_container *container) { if (container->type == C_VIEW || container->type == C_CONTAINER) { ipc_event_window(container, "new"); + } else if (container->type == C_WORKSPACE) { + ipc_event_workspace(NULL, container, "init"); } } From f0310933c89ba062a13df0b319d65f0574445ab8 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 13 Jul 2018 17:15:52 +0100 Subject: [PATCH 08/24] ipc: add window::close event --- sway/tree/container.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index f082e8b1d..478550526 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -321,7 +321,11 @@ static struct sway_container *container_destroy_noreaping( } wl_signal_emit(&con->events.destroy, con); - ipc_event_window(con, "close"); + + // emit IPC event + if (con->type == C_VIEW) { + ipc_event_window(con, "close"); + } // The below functions move their children to somewhere else. if (con->type == C_OUTPUT) { From dd1d6255f0e558f2d62e03f701440a57f65254b2 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 13 Jul 2018 17:16:32 +0100 Subject: [PATCH 09/24] ipc: add window::focus event --- sway/input/seat.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/input/seat.c b/sway/input/seat.c index a4a449e49..c85e92420 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -766,6 +766,10 @@ void seat_set_focus_warp(struct sway_seat *seat, } } + if (container->type == C_VIEW) { + ipc_event_window(container, "focus"); + } + seat->has_focus = (container != NULL); update_debug_tree(); From 4f8f363dda2495810e419be6e79c3869bb7f17d8 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 13 Jul 2018 17:19:16 +0100 Subject: [PATCH 10/24] ipc: add window::title event --- sway/tree/view.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/tree/view.c b/sway/tree/view.c index 8f54cc119..7300f207e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -864,6 +864,8 @@ void view_update_title(struct sway_view *view, bool force) { // Update title after the global font height is updated container_update_title_textures(view->swayc); + + ipc_event_window(view->swayc, "title"); } static bool find_by_mark_iterator(struct sway_container *con, From 686c084cec0b1143c877e8c0088732fad5229ce4 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 13 Jul 2018 21:55:04 +0100 Subject: [PATCH 11/24] ipc: add workspace::empty event --- sway/tree/container.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index 478550526..3b3c5e2e3 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -325,6 +325,8 @@ static struct sway_container *container_destroy_noreaping( // emit IPC event if (con->type == C_VIEW) { ipc_event_window(con, "close"); + } else if (con->type == C_WORKSPACE) { + ipc_event_workspace(NULL, con, "empty"); } // The below functions move their children to somewhere else. From dd6debf367420d0771cc0326ecb2511c1ce05ac1 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 13 Jul 2018 23:22:34 +0100 Subject: [PATCH 12/24] ipc: add barconfig_update event on config reload --- sway/commands/reload.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sway/commands/reload.c b/sway/commands/reload.c index cea6a94bc..36c6acce2 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -1,17 +1,45 @@ +#define _XOPEN_SOURCE 500 +#include #include "sway/commands.h" #include "sway/config.h" +#include "sway/ipc-server.h" #include "sway/tree/arrange.h" +#include "list.h" struct cmd_results *cmd_reload(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { return error; } + + // store bar ids to check against new bars for barconfig_update events + list_t *bar_ids = create_list(); + for (int i = 0; i < config->bars->length; ++i) { + struct bar_config *bar = config->bars->items[i]; + list_add(bar_ids, strdup(bar->id)); + } + if (!load_main_config(config->current_config_path, true)) { return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); } load_swaybars(); + + for (int i = 0; i < config->bars->length; ++i) { + struct bar_config *bar = config->bars->items[i]; + for (int j = 0; j < bar_ids->length; ++j) { + if (strcmp(bar->id, bar_ids->items[j]) == 0) { + ipc_event_barconfig_update(bar); + break; + } + } + } + + for (int i = 0; i < bar_ids->length; ++i) { + free(bar_ids->items[i]); + } + list_free(bar_ids); + arrange_windows(&root_container); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } From 317217f2c87aba4463806e211c22296ac9230b6c Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sat, 14 Jul 2018 11:10:36 +0100 Subject: [PATCH 13/24] ipc: add window::mark event --- include/sway/tree/view.h | 2 ++ sway/commands/mark.c | 2 +- sway/ipc-json.c | 9 +++++++++ sway/tree/view.c | 13 +++++++++---- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 0152ed554..800df0731 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -311,6 +311,8 @@ void view_clear_marks(struct sway_view *view); bool view_has_mark(struct sway_view *view, char *mark); +void view_add_mark(struct sway_view *view, char *mark); + void view_update_marks_textures(struct sway_view *view); /** diff --git a/sway/commands/mark.c b/sway/commands/mark.c index 5a897e698..9ea8c3015 100644 --- a/sway/commands/mark.c +++ b/sway/commands/mark.c @@ -58,7 +58,7 @@ struct cmd_results *cmd_mark(int argc, char **argv) { view_find_and_unmark(mark); if (!toggle || !had_mark) { - list_add(view->marks, strdup(mark)); + view_add_mark(view, mark); } free(mark); diff --git a/sway/ipc-json.c b/sway/ipc-json.c index c49ea47ef..4c2bcc986 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -201,6 +201,15 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object bool urgent = c->type == C_VIEW ? view_is_urgent(c->sway_view) : container_has_urgent_child(c); json_object_object_add(object, "urgent", json_object_new_boolean(urgent)); + + if (c->type == C_VIEW) { + json_object *marks = json_object_new_array(); + list_t *view_marks = c->sway_view->marks; + for (int i = 0; i < view_marks->length; ++i) { + json_object_array_add(marks, json_object_new_string(view_marks->items[i])); + } + json_object_object_add(object, "marks", marks); + } } static void focus_inactive_children_iterator(struct sway_container *c, void *data) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 7300f207e..48b39e809 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -888,6 +888,7 @@ bool view_find_and_unmark(char *mark) { free(view_mark); list_del(view->marks, i); view_update_marks_textures(view); + ipc_event_window(container, "mark"); return true; } } @@ -895,11 +896,10 @@ bool view_find_and_unmark(char *mark) { } void view_clear_marks(struct sway_view *view) { - for (int i = 0; i < view->marks->length; ++i) { - free(view->marks->items[i]); + while (view->marks->length) { + list_del(view->marks, 0); + ipc_event_window(view->swayc, "mark"); } - list_free(view->marks); - view->marks = create_list(); } bool view_has_mark(struct sway_view *view, char *mark) { @@ -912,6 +912,11 @@ bool view_has_mark(struct sway_view *view, char *mark) { return false; } +void view_add_mark(struct sway_view *view, char *mark) { + list_add(view->marks, strdup(mark)); + ipc_event_window(view->swayc, "mark"); +} + static void update_marks_texture(struct sway_view *view, struct wlr_texture **texture, struct border_colors *class) { struct sway_container *output = container_parent(view->swayc, C_OUTPUT); From 07101a570750f47fa5d4fb81739a40168b6c8ea6 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Mon, 16 Jul 2018 14:01:35 +0100 Subject: [PATCH 14/24] ipc: only emit window::create event for views --- 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 3b3c5e2e3..92d9ce062 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -62,7 +62,7 @@ void container_create_notify(struct sway_container *container) { // TODO send ipc event type based on the container type wl_signal_emit(&root_container.sway_root->events.new_container, container); - if (container->type == C_VIEW || container->type == C_CONTAINER) { + if (container->type == C_VIEW) { ipc_event_window(container, "new"); } else if (container->type == C_WORKSPACE) { ipc_event_workspace(NULL, container, "init"); From 4bf253855f1946ffca5a41085b8ae3eb79ca62c4 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 18 Jul 2018 10:47:44 +0100 Subject: [PATCH 15/24] ipc: fix workspace::move calls argument order --- sway/tree/container.c | 2 +- sway/tree/layout.c | 2 +- sway/tree/output.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 92d9ce062..b6ff4d308 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -283,7 +283,7 @@ static struct sway_container *container_output_destroy( container_remove_child(workspace); if (!workspace_is_empty(workspace)) { container_add_child(new_output, workspace); - ipc_event_workspace(workspace, NULL, "move"); + ipc_event_workspace(NULL, workspace, "move"); } else { container_destroy(workspace); } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index a0764a549..b833e8e1c 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -217,7 +217,7 @@ void container_move_to(struct sway_container *container, container_sort_workspaces(new_parent); seat_set_focus(seat, new_parent); workspace_output_raise_priority(container, old_parent, new_parent); - ipc_event_workspace(container, NULL, "move"); + ipc_event_workspace(NULL, container, "move"); } container_notify_subtree_changed(old_parent); container_notify_subtree_changed(new_parent); diff --git a/sway/tree/output.c b/sway/tree/output.c index da535c180..31e3bf9b3 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -22,7 +22,7 @@ static void restore_workspaces(struct sway_container *output) { if (highest == output) { container_remove_child(ws); container_add_child(output, ws); - ipc_event_workspace(ws, NULL, "move"); + ipc_event_workspace(NULL, ws, "move"); j--; } } From e0e638281e193103b44105cb1689b2ec25cae7e8 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 18 Jul 2018 10:50:48 +0100 Subject: [PATCH 16/24] ipc: add window::move events --- sway/tree/layout.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sway/tree/layout.c b/sway/tree/layout.c index b833e8e1c..a0f9b6de7 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -218,6 +218,8 @@ void container_move_to(struct sway_container *container, seat_set_focus(seat, new_parent); workspace_output_raise_priority(container, old_parent, new_parent); ipc_event_workspace(NULL, container, "move"); + } else if (container->type == C_VIEW) { + ipc_event_window(container, "move"); } container_notify_subtree_changed(old_parent); container_notify_subtree_changed(new_parent); @@ -578,6 +580,10 @@ void container_move(struct sway_container *container, container_notify_subtree_changed(old_parent); container_notify_subtree_changed(container->parent); + if (container->type == C_VIEW) { + ipc_event_window(container, "move"); + } + if (old_parent) { seat_set_focus(config->handler_context.seat, old_parent); seat_set_focus(config->handler_context.seat, container); From 6865b8aae9736e73a2153bce89d979737f8162cc Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 18 Jul 2018 11:37:50 +0100 Subject: [PATCH 17/24] ipc: add binding event --- include/sway/config.h | 2 -- include/sway/ipc-server.h | 1 + sway/commands/bind.c | 52 ++++++++++++++++++++++++++- sway/ipc-server.c | 76 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 3 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 0f74b4392..909b6827e 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -488,8 +488,6 @@ int sway_binding_cmp_keys(const void *a, const void *b); void free_sway_binding(struct sway_binding *sb); -struct sway_binding *sway_binding_dup(struct sway_binding *sb); - void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding); void load_swaybars(); diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index a11735cfe..4b6d0e256 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -17,5 +17,6 @@ void ipc_event_window(struct sway_container *window, const char *change); void ipc_event_barconfig_update(struct bar_config *bar); void ipc_event_mode(const char *mode, bool pango); void ipc_event_shutdown(const char *reason); +void ipc_event_binding(struct sway_binding *binding); #endif diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 133fd0890..8270b958d 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -1,3 +1,4 @@ +#define _XOPEN_SOURCE 500 #ifdef __linux__ #include #elif __FreeBSD__ @@ -5,9 +6,11 @@ #endif #include #include +#include #include #include "sway/commands.h" #include "sway/config.h" +#include "sway/ipc-server.h" #include "list.h" #include "log.h" #include "stringop.h" @@ -27,6 +30,33 @@ void free_sway_binding(struct sway_binding *binding) { free(binding); } +static struct sway_binding *sway_binding_dup(struct sway_binding *sb) { + struct sway_binding *new_sb = calloc(1, sizeof(struct sway_binding)); + if (!new_sb) { + return NULL; + } + + new_sb->type = sb->type; + new_sb->order = sb->order; + new_sb->flags = sb->flags; + new_sb->modifiers = sb->modifiers; + new_sb->command = strdup(sb->command); + + new_sb->keys = create_list(); + int i; + for (i = 0; i < sb->keys->length; ++i) { + xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); + if (!key) { + free_sway_binding(new_sb); + return NULL; + } + *key = *(xkb_keysym_t *)sb->keys->items[i]; + list_add(new_sb->keys, key); + } + + return new_sb; +} + /** * Returns true if the bindings have the same key and modifier combinations. * Note that keyboard layout is not considered, so the bindings might actually @@ -275,11 +305,31 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) { wlr_log(WLR_DEBUG, "running command for binding: %s", binding->command); + + struct sway_binding *binding_copy = binding; + bool reload = false; + // if this is a reload command we need to make a duplicate of the + // binding since it will be gone after the reload has completed. + if (strcasecmp(binding->command, "reload") == 0) { + reload = true; + binding_copy = sway_binding_dup(binding); + if (!binding_copy) { + wlr_log(WLR_ERROR, "Failed to duplicate binding during reload"); + return; + } + } + config->handler_context.seat = seat; struct cmd_results *results = execute_command(binding->command, NULL); - if (results->status != CMD_SUCCESS) { + if (results->status == CMD_SUCCESS) { + ipc_event_binding(binding_copy); + } else { wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", binding->command, results->error); } + + if (reload) { // free the binding if we made a copy + free_sway_binding(binding_copy); + } free_cmd_results(results); } diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 72031e243..8fceafa21 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -3,12 +3,18 @@ // Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0) #define _XOPEN_SOURCE 700 #endif +#ifdef __linux__ +#include +#elif __FreeBSD__ +#include +#endif #include #include #include #include #include #include +#include #include #include #include @@ -28,6 +34,7 @@ #include "sway/tree/view.h" #include "list.h" #include "log.h" +#include "util.h" static int ipc_socket = -1; static struct wl_event_source *ipc_event_source = NULL; @@ -367,6 +374,75 @@ void ipc_event_shutdown(const char *reason) { json_object_put(json); } +void ipc_event_binding(struct sway_binding *binding) { + if (!ipc_has_event_listeners(IPC_EVENT_BINDING)) { + return; + } + wlr_log(WLR_DEBUG, "Sending binding event"); + + json_object *json_binding = json_object_new_object(); + json_object_object_add(json_binding, "command", json_object_new_string(binding->command)); + + const char *names[10]; + int len = get_modifier_names(names, binding->modifiers); + json_object *modifiers = json_object_new_array(); + for (int i = 0; i < len; ++i) { + json_object_array_add(modifiers, json_object_new_string(names[i])); + } + json_object_object_add(json_binding, "event_state_mask", modifiers); + + json_object *input_codes = json_object_new_array(); + int input_code = 0; + json_object *symbols = json_object_new_array(); + json_object *symbol = NULL; + + if (binding->type == BINDING_KEYCODE) { // bindcode: populate input_codes + uint32_t keycode; + for (int i = 0; i < binding->keys->length; ++i) { + keycode = *(uint32_t *)binding->keys->items[i]; + json_object_array_add(input_codes, json_object_new_int(keycode)); + if (i == 0) { + input_code = keycode; + } + } + } else { // bindsym/mouse: populate symbols + uint32_t keysym; + char buffer[64]; + for (int i = 0; i < binding->keys->length; ++i) { + keysym = *(uint32_t *)binding->keys->items[i]; + if (keysym >= BTN_LEFT && keysym <= BTN_LEFT + 8) { + snprintf(buffer, 64, "button%u", keysym - BTN_LEFT + 1); + } else if (xkb_keysym_get_name(keysym, buffer, 64) < 0) { + continue; + } + + json_object *str = json_object_new_string(buffer); + if (i == 0) { + // str is owned by both symbol and symbols. Make sure + // to bump the ref count. + json_object_array_add(symbols, json_object_get(str)); + symbol = str; + } else { + json_object_array_add(symbols, str); + } + } + } + + json_object_object_add(json_binding, "input_codes", input_codes); + json_object_object_add(json_binding, "input_code", json_object_new_int(input_code)); + json_object_object_add(json_binding, "symbols", symbols); + json_object_object_add(json_binding, "symbol", symbol); + json_object_object_add(json_binding, "input_type", binding->type == BINDING_MOUSE ? + json_object_new_string("mouse") : json_object_new_string("keyboard")); + + json_object *json = json_object_new_object(); + json_object_object_add(json, "change", json_object_new_string("run")); + json_object_object_add(json, "binding", json_binding); + const char *json_string = json_object_to_json_string(json); + ipc_send_event(json_string, IPC_EVENT_BINDING); + json_object_put(json); +} + int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; From d898e035ba539005a8d7fa8283191f4c4054612e Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 18 Jul 2018 11:38:06 +0100 Subject: [PATCH 18/24] ipc: add workspace::reload event --- sway/commands/reload.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 36c6acce2..5c1b19b46 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -22,6 +22,7 @@ struct cmd_results *cmd_reload(int argc, char **argv) { if (!load_main_config(config->current_config_path, true)) { return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); } + ipc_event_workspace(NULL, NULL, "reload"); load_swaybars(); From 75aba004603e35c80eda397c2e987f2c3e75cbf5 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 18 Jul 2018 11:40:16 +0100 Subject: [PATCH 19/24] ipc: always include old property in workspace events --- sway/ipc-server.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 8fceafa21..dc6b353ba 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -298,13 +298,11 @@ void ipc_event_workspace(struct sway_container *old, wlr_log(WLR_DEBUG, "Sending workspace::%s event", change); json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(change)); - if (strcmp("focus", change) == 0) { - if (old) { - json_object_object_add(obj, "old", - ipc_json_describe_container_recursive(old)); - } else { - json_object_object_add(obj, "old", NULL); - } + if (old) { + json_object_object_add(obj, "old", + ipc_json_describe_container_recursive(old)); + } else { + json_object_object_add(obj, "old", NULL); } if (new) { From 33433c64347eb0bfd7c1465a3b60579fa88ef724 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 18 Jul 2018 11:52:29 +0100 Subject: [PATCH 20/24] Add missing swaymsg completions --- completions/bash/swaymsg | 3 ++- completions/zsh/_swaymsg | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/completions/bash/swaymsg b/completions/bash/swaymsg index 8ec90b6f5..e4b2c1b75 100644 --- a/completions/bash/swaymsg +++ b/completions/bash/swaymsg @@ -14,7 +14,8 @@ _swaymsg() 'get_marks' 'get_bar_config' 'get_version' - 'get_clipboard' + 'get_binding_modes' + 'get_config' ) short=( diff --git a/completions/zsh/_swaymsg b/completions/zsh/_swaymsg index 2e39deb6c..28de474dc 100644 --- a/completions/zsh/_swaymsg +++ b/completions/zsh/_swaymsg @@ -22,6 +22,8 @@ types=( 'get_marks' 'get_bar_config' 'get_version' +'get_binding_modes' +'get_config' ) _arguments -s \ From 3edaf2ce2a8a4753c162491329a7dfa492ff7e77 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 18 Jul 2018 12:30:39 +0100 Subject: [PATCH 21/24] ipc: add tick event --- completions/bash/swaymsg | 1 + completions/zsh/_swaymsg | 1 + include/ipc.h | 2 ++ sway/ipc-server.c | 30 ++++++++++++++++++++++++++++++ swaymsg/main.c | 8 +++++++- swaymsg/swaymsg.1.scd | 3 +++ 6 files changed, 44 insertions(+), 1 deletion(-) diff --git a/completions/bash/swaymsg b/completions/bash/swaymsg index e4b2c1b75..20092bdc4 100644 --- a/completions/bash/swaymsg +++ b/completions/bash/swaymsg @@ -16,6 +16,7 @@ _swaymsg() 'get_version' 'get_binding_modes' 'get_config' + 'send_tick' ) short=( diff --git a/completions/zsh/_swaymsg b/completions/zsh/_swaymsg index 28de474dc..a7a1c8e0d 100644 --- a/completions/zsh/_swaymsg +++ b/completions/zsh/_swaymsg @@ -24,6 +24,7 @@ types=( 'get_version' 'get_binding_modes' 'get_config' +'send_tick' ) _arguments -s \ diff --git a/include/ipc.h b/include/ipc.h index ffc57d1be..2138d3fa4 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -15,6 +15,7 @@ enum ipc_command_type { IPC_GET_VERSION = 7, IPC_GET_BINDING_MODES = 8, IPC_GET_CONFIG = 9, + IPC_SEND_TICK = 10, // sway-specific command types IPC_GET_INPUTS = 100, @@ -28,6 +29,7 @@ enum ipc_command_type { IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4), IPC_EVENT_BINDING = ((1<<31) | 5), IPC_EVENT_SHUTDOWN = ((1<<31) | 6), + IPC_EVENT_TICK = ((1<<31) | 7), IPC_EVENT_MODIFIER = ((1<<31) | 16), IPC_EVENT_INPUT = ((1<<31) | 17), }; diff --git a/sway/ipc-server.c b/sway/ipc-server.c index dc6b353ba..636335670 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -441,6 +441,21 @@ void ipc_event_binding(struct sway_binding *binding) { json_object_put(json); } +static void ipc_event_tick(const char *payload) { + if (!ipc_has_event_listeners(IPC_EVENT_TICK)) { + return; + } + wlr_log(WLR_DEBUG, "Sending tick event"); + + json_object *json = json_object_new_object(); + json_object_object_add(json, "first", json_object_new_boolean(false)); + json_object_object_add(json, "payload", json_object_new_string(payload)); + + const char *json_string = json_object_to_json_string(json); + ipc_send_event(json_string, IPC_EVENT_TICK); + json_object_put(json); +} + int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; @@ -582,6 +597,13 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_SEND_TICK: + { + ipc_event_tick(buf); + ipc_send_reply(client, "{\"success\": true}", 17); + goto exit_cleanup; + } + case IPC_GET_OUTPUTS: { json_object *outputs = json_object_new_array(); @@ -628,6 +650,7 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + bool is_tick = false; // parse requested event types for (size_t i = 0; i < json_object_array_length(request); i++) { const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); @@ -645,6 +668,9 @@ void ipc_client_handle_command(struct ipc_client *client) { client->subscribed_events |= event_mask(IPC_EVENT_MODIFIER); } else if (strcmp(event_type, "binding") == 0) { client->subscribed_events |= event_mask(IPC_EVENT_BINDING); + } else if (strcmp(event_type, "tick") == 0) { + client->subscribed_events |= event_mask(IPC_EVENT_TICK); + is_tick = true; } else { client_valid = ipc_send_reply(client, "{\"success\": false}", 18); @@ -656,6 +682,10 @@ void ipc_client_handle_command(struct ipc_client *client) { json_object_put(request); client_valid = ipc_send_reply(client, "{\"success\": true}", 17); + if (is_tick) { + client->current_command = IPC_EVENT_TICK; + ipc_send_reply(client, "{\"first\": true, \"payload\": \"\"}", 30); + } goto exit_cleanup; } diff --git a/swaymsg/main.c b/swaymsg/main.c index c4141ca57..3767daf32 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -250,12 +250,16 @@ static void pretty_print(int type, json_object *resp) { if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES && type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS && type != IPC_GET_VERSION && type != IPC_GET_SEATS && - type != IPC_GET_CONFIG) { + type != IPC_GET_CONFIG && type != IPC_SEND_TICK) { printf("%s\n", json_object_to_json_string_ext(resp, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); return; } + if (type == IPC_SEND_TICK) { + return; + } + if (type == IPC_GET_VERSION) { pretty_print_version(resp); return; @@ -384,6 +388,8 @@ int main(int argc, char **argv) { type = IPC_GET_BINDING_MODES; } else if (strcasecmp(cmdtype, "get_config") == 0) { type = IPC_GET_CONFIG; + } else if (strcasecmp(cmdtype, "send_tick") == 0) { + type = IPC_SEND_TICK; } else { sway_abort("Unknown message type %s", cmdtype); } diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index a6e279da9..8cf1b2228 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd @@ -64,3 +64,6 @@ _swaymsg_ [options...] [message] *get\_config* Gets a JSON-encoded copy of the current configuration. + +*send\_tick* + Sends a tick event to all subscribed clients. From b2ac234569ff98de583d9e7755526cadf960f772 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 18 Jul 2018 21:52:15 +0100 Subject: [PATCH 22/24] ipc: fix workspace::focus event behaviour --- sway/input/seat.c | 4 +++- sway/tree/layout.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index c85e92420..76050aa92 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -739,7 +739,9 @@ void seat_set_focus_warp(struct sway_seat *seat, if (last_focus) { if (last_workspace) { - ipc_event_workspace(last_workspace, container, "focus"); + if (last_workspace != new_workspace) { + ipc_event_workspace(last_workspace, new_workspace, "focus"); + } if (!workspace_is_visible(last_workspace) && workspace_is_empty(last_workspace)) { if (last_workspace == last_focus) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index a0f9b6de7..9fbbccafc 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -598,7 +598,7 @@ void container_move(struct sway_container *container, next_ws = container_parent(next_ws, C_WORKSPACE); } if (last_ws && next_ws && last_ws != next_ws) { - ipc_event_workspace(last_ws, container, "focus"); + ipc_event_workspace(last_ws, next_ws, "focus"); workspace_detect_urgent(last_ws); workspace_detect_urgent(next_ws); } From 03eaf444a4a432e5712d40f93d849b51d2028b63 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 18 Jul 2018 21:55:14 +0100 Subject: [PATCH 23/24] ipc: prevent emitting a workspace::focus event when moving a container to a different workspace or output When a container is moved from, say, workspace 1 to workspace 2, workspace 2 is focused in order to arrange the windows before focus is moved back to workspace 1, which caused a workspace:focus event from workspace 2 to workspace 1 to be emitted. This commit inhibits that event. --- include/sway/input/seat.h | 2 +- sway/commands/move.c | 4 ++-- sway/input/cursor.c | 6 +++--- sway/input/seat.c | 6 +++--- sway/tree/layout.c | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 07febe2ca..92387601a 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -99,7 +99,7 @@ void seat_configure_xcursor(struct sway_seat *seat); void seat_set_focus(struct sway_seat *seat, struct sway_container *container); void seat_set_focus_warp(struct sway_seat *seat, - struct sway_container *container, bool warp); + struct sway_container *container, bool warp, bool notify); void seat_set_focus_surface(struct sway_seat *seat, struct wlr_surface *surface, bool unfocus); diff --git a/sway/commands/move.c b/sway/commands/move.c index 1aae38381..46ebcd831 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -98,7 +98,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, container_move_to(current, destination); struct sway_container *focus = seat_get_focus_inactive( config->handler_context.seat, old_parent); - seat_set_focus(config->handler_context.seat, focus); + seat_set_focus_warp(config->handler_context.seat, focus, true, false); container_reap_empty(old_parent); container_reap_empty(destination->parent); @@ -135,7 +135,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, struct sway_container *old_parent = current->parent; struct sway_container *old_ws = container_parent(current, C_WORKSPACE); container_move_to(current, focus); - seat_set_focus(config->handler_context.seat, old_parent); + seat_set_focus_warp(config->handler_context.seat, old_parent, true, false); container_reap_empty(old_parent); container_reap_empty(focus->parent); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 96ac7b330..d6fdc1da6 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -349,7 +349,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, output = container_parent(c, C_OUTPUT); } if (output != focus) { - seat_set_focus_warp(seat, c, false); + seat_set_focus_warp(seat, c, false, true); } } else if (c->type == C_VIEW) { // Focus c if the following are true: @@ -359,13 +359,13 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) && c != prev_c && view_is_visible(c->sway_view)) { - seat_set_focus_warp(seat, c, false); + seat_set_focus_warp(seat, c, false, true); } else { struct sway_container *next_focus = seat_get_focus_inactive(seat, &root_container); if (next_focus && next_focus->type == C_VIEW && view_is_visible(next_focus->sway_view)) { - seat_set_focus_warp(seat, next_focus, false); + seat_set_focus_warp(seat, next_focus, false, true); } } } diff --git a/sway/input/seat.c b/sway/input/seat.c index 76050aa92..fe3cbc537 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -617,7 +617,7 @@ static int handle_urgent_timeout(void *data) { } void seat_set_focus_warp(struct sway_seat *seat, - struct sway_container *container, bool warp) { + struct sway_container *container, bool warp, bool notify) { if (seat->focused_layer) { return; } @@ -739,7 +739,7 @@ void seat_set_focus_warp(struct sway_seat *seat, if (last_focus) { if (last_workspace) { - if (last_workspace != new_workspace) { + if (notify && last_workspace != new_workspace) { ipc_event_workspace(last_workspace, new_workspace, "focus"); } if (!workspace_is_visible(last_workspace) @@ -779,7 +779,7 @@ void seat_set_focus_warp(struct sway_seat *seat, void seat_set_focus(struct sway_seat *seat, struct sway_container *container) { - seat_set_focus_warp(seat, container, true); + seat_set_focus_warp(seat, container, true, true); } void seat_set_focus_surface(struct sway_seat *seat, diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 9fbbccafc..1f82e534a 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -1001,13 +1001,13 @@ static void swap_focus(struct sway_container *con1, if (focus == con1 && (con2->parent->layout == L_TABBED || con2->parent->layout == L_STACKED)) { if (workspace_is_visible(ws2)) { - seat_set_focus_warp(seat, con2, false); + seat_set_focus_warp(seat, con2, false, true); } seat_set_focus(seat, ws1 != ws2 ? con2 : con1); } else if (focus == con2 && (con1->parent->layout == L_TABBED || con1->parent->layout == L_STACKED)) { if (workspace_is_visible(ws1)) { - seat_set_focus_warp(seat, con1, false); + seat_set_focus_warp(seat, con1, false, true); } seat_set_focus(seat, ws1 != ws2 ? con1 : con2); } else if (ws1 != ws2) { From 46cfa8ff56acff0139b2e24300cbc3ea19da723f Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 1 Aug 2018 16:22:06 +0100 Subject: [PATCH 24/24] ipc: remove extraneous values Removes IPC_EVENT_MODIFIER and IPC_EVENT_INPUT, which were sway-specific and unused --- include/ipc.h | 2 -- sway/ipc-server.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/include/ipc.h b/include/ipc.h index 2138d3fa4..a3f60e193 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -30,8 +30,6 @@ enum ipc_command_type { IPC_EVENT_BINDING = ((1<<31) | 5), IPC_EVENT_SHUTDOWN = ((1<<31) | 6), IPC_EVENT_TICK = ((1<<31) | 7), - IPC_EVENT_MODIFIER = ((1<<31) | 16), - IPC_EVENT_INPUT = ((1<<31) | 17), }; #endif diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 636335670..7d2d8969a 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -664,8 +664,6 @@ void ipc_client_handle_command(struct ipc_client *client) { client->subscribed_events |= event_mask(IPC_EVENT_SHUTDOWN); } else if (strcmp(event_type, "window") == 0) { client->subscribed_events |= event_mask(IPC_EVENT_WINDOW); - } else if (strcmp(event_type, "modifier") == 0) { - client->subscribed_events |= event_mask(IPC_EVENT_MODIFIER); } else if (strcmp(event_type, "binding") == 0) { client->subscribed_events |= event_mask(IPC_EVENT_BINDING); } else if (strcmp(event_type, "tick") == 0) {