From acd79e1505c06089e4fb9fb6c0c6e1d351ba9176 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 26 Jun 2018 20:32:09 -0400 Subject: Implement pid->workspace tracking When you spawn a process with the exec command, sway now notes the workspace you had focused and the pid of the child process, then assigns that workspace to the child when its window appears. Some of this is carried over from sway 0.15, but with some major refactoring and centralization of state. --- sway/tree/view.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 06e9edc5..24fb6864 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "list.h" #include "log.h" #include "sway/criteria.h" @@ -492,9 +493,21 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { return; } + pid_t pid; + if (view->type == SWAY_VIEW_XWAYLAND) { + struct wlr_xwayland_surface *surf = + wlr_xwayland_surface_from_wlr_surface(wlr_surface); + pid = surf->pid; + } else { + struct wl_client *client = + wl_resource_get_client(wlr_surface->resource); + wl_client_get_credentials(client, &pid, NULL, NULL); + } + struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = + struct sway_container *target_sibling = seat_get_focus_inactive(seat, &root_container); + struct sway_container *prev_focus = target_sibling; struct sway_container *cont = NULL; // Check if there's any `assign` criteria for the view @@ -508,18 +521,31 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { if (!workspace) { workspace = workspace_create(NULL, criteria->target); } - focus = seat_get_focus_inactive(seat, workspace); + prev_focus = target_sibling; + target_sibling = seat_get_focus_inactive(seat, workspace); } else { // TODO: CT_ASSIGN_OUTPUT } } + list_free(criterias); + + if (!workspace) { + workspace = workspace_for_pid(pid); + if (workspace) { + prev_focus = target_sibling; + target_sibling = seat_get_focus_inactive(seat, workspace); + } + } // If we're about to launch the view into the floating container, then // launch it as a tiled view in the root of the workspace instead. - if (container_is_floating(focus)) { - focus = focus->parent->parent; + if (container_is_floating(target_sibling)) { + if (prev_focus == target_sibling) { + prev_focus = target_sibling->parent->parent; + } + target_sibling = target_sibling->parent->parent; } - free(criterias); - cont = container_view_create(focus, view); + + cont = container_view_create(target_sibling, view); view->surface = wlr_surface; view->swayc = cont; @@ -538,9 +564,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { container_set_floating(view->swayc, true); } - input_manager_set_focus(input_manager, cont); - if (workspace) { - workspace_switch(workspace); + if (prev_focus == target_sibling) { + input_manager_set_focus(input_manager, cont); } view_update_title(view, false); -- cgit v1.2.3 From 9fbe13b9be18c732b58033a57a22a299af91a170 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 18 Jul 2018 16:13:28 +1000 Subject: Implement floating_modifier and mouse operations for floating views This implements the following: * `floating_modifier` configuration directive * Drag a floating window by its title bar * Hold mod + drag a floating window from anywhere * Resize a floating view by dragging the border * Resize a floating view by holding mod and right clicking anywhere on the view * Resize a floating view and keep aspect ratio by holding shift while resizing using either method * Mouse cursor turns into resize when hovering floating border or corner --- sway/tree/view.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 7881e6d7..24594950 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -387,6 +387,8 @@ void view_set_fullscreen(struct sway_view *view, bool fullscreen) { } } + container_end_mouse_operation(view->swayc); + ipc_event_window(view->swayc, "fullscreen_mode"); } -- cgit v1.2.3 From 011d1ebfa4219eb666487529a5a5e7189c14fd40 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 21 Jul 2018 12:13:00 +1000 Subject: Consider view's min/max sizes when resizing --- sway/tree/view.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 24594950..89150a69 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -141,6 +141,19 @@ const char *view_get_shell(struct sway_view *view) { return "unknown"; } +void view_get_constraints(struct sway_view *view, double *min_width, + double *max_width, double *min_height, double *max_height) { + if (view->impl->get_constraints) { + view->impl->get_constraints(view, + min_width, max_width, min_height, max_height); + } else { + *min_width = DBL_MIN; + *max_width = DBL_MAX; + *min_height = DBL_MIN; + *max_height = DBL_MAX; + } +} + uint32_t view_configure(struct sway_view *view, double lx, double ly, int width, int height) { if (view->impl->configure) { -- cgit v1.2.3 From 81e8f31cc6f284b54ab206e14af7ecbc1a9ed1bb Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sun, 22 Jul 2018 14:10:40 +1000 Subject: Implement scratchpad Implements the following commands: * move scratchpad * scratchpad show * [criteria] scratchpad show Also fixes these: * Fix memory leak when executing command with criteria (use `list_free(views)` instead of `free(views)`) * Fix crash when running `move to` with no further arguments --- sway/tree/view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 89150a69..9d88d7aa 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1065,7 +1065,7 @@ void view_update_marks_textures(struct sway_view *view) { } bool view_is_visible(struct sway_view *view) { - if (!view->swayc || view->swayc->destroying) { + if (!view->swayc || view->swayc->destroying || !view->swayc->parent) { return false; } struct sway_container *workspace = -- cgit v1.2.3 From 24ad1c3983192b47345566fd876e26b45160d68e Mon Sep 17 00:00:00 2001 From: Pascal Pascher Date: Tue, 24 Jul 2018 22:16:06 +0200 Subject: Added meson option "enable_xwayland" (default: true) to enable/disable xwayland support --- sway/tree/view.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index a55c8a29..e99b938e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,7 +3,9 @@ #include #include #include +#ifdef HAVE_XWAYLAND #include +#endif #include "list.h" #include "log.h" #include "sway/criteria.h" @@ -108,14 +110,14 @@ const char *view_get_instance(struct sway_view *view) { } return NULL; } - +#ifdef HAVE_XWAYLAND uint32_t view_get_x11_window_id(struct sway_view *view) { if (view->impl->get_int_prop) { return view->impl->get_int_prop(view, VIEW_PROP_X11_WINDOW_ID); } return 0; } - +#endif const char *view_get_window_role(struct sway_view *view) { if (view->impl->get_string_prop) { return view->impl->get_string_prop(view, VIEW_PROP_WINDOW_ROLE); @@ -136,8 +138,10 @@ const char *view_get_shell(struct sway_view *view) { return "xdg_shell_v6"; case SWAY_VIEW_XDG_SHELL: return "xdg_shell"; + #ifdef HAVE_XWAYLAND case SWAY_VIEW_XWAYLAND: return "xwayland"; + #endif } return "unknown"; } @@ -563,6 +567,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { } pid_t pid; + #ifdef HAVE_XWAYLAND if (view->type == SWAY_VIEW_XWAYLAND) { struct wlr_xwayland_surface *surf = wlr_xwayland_surface_from_wlr_surface(wlr_surface); @@ -572,6 +577,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { wl_resource_get_client(wlr_surface->resource); wl_client_get_credentials(client, &pid, NULL, NULL); } + #else + struct wl_client *client = + wl_resource_get_client(wlr_surface->resource); + wl_client_get_credentials(client, &pid, NULL, NULL); + #endif struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *target_sibling = @@ -825,11 +835,13 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { wlr_xdg_surface_v6_from_wlr_surface(wlr_surface); return view_from_wlr_xdg_surface_v6(xdg_surface_v6); } + #ifdef HAVE_XWAYLAND if (wlr_surface_is_xwayland_surface(wlr_surface)) { struct wlr_xwayland_surface *xsurface = wlr_xwayland_surface_from_wlr_surface(wlr_surface); return view_from_wlr_xwayland_surface(xsurface); } + #endif if (wlr_surface_is_subsurface(wlr_surface)) { struct wlr_subsurface *subsurface = wlr_subsurface_from_wlr_surface(wlr_surface); -- cgit v1.2.3 From 2bf893248a94c7f70a9557aad4a8228731041eeb Mon Sep 17 00:00:00 2001 From: Pascal Pascher Date: Tue, 24 Jul 2018 23:37:41 +0200 Subject: style fixes, exclude sway/desctop/xwayland.c when enable_xwayland: false --- sway/tree/view.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index e99b938e..2eff80a8 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -138,10 +138,10 @@ const char *view_get_shell(struct sway_view *view) { return "xdg_shell_v6"; case SWAY_VIEW_XDG_SHELL: return "xdg_shell"; - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND case SWAY_VIEW_XWAYLAND: return "xwayland"; - #endif +#endif } return "unknown"; } @@ -567,7 +567,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { } pid_t pid; - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND if (view->type == SWAY_VIEW_XWAYLAND) { struct wlr_xwayland_surface *surf = wlr_xwayland_surface_from_wlr_surface(wlr_surface); @@ -577,11 +577,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { wl_resource_get_client(wlr_surface->resource); wl_client_get_credentials(client, &pid, NULL, NULL); } - #else +#else struct wl_client *client = wl_resource_get_client(wlr_surface->resource); wl_client_get_credentials(client, &pid, NULL, NULL); - #endif +#endif struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *target_sibling = @@ -835,13 +835,13 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { wlr_xdg_surface_v6_from_wlr_surface(wlr_surface); return view_from_wlr_xdg_surface_v6(xdg_surface_v6); } - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND if (wlr_surface_is_xwayland_surface(wlr_surface)) { struct wlr_xwayland_surface *xsurface = wlr_xwayland_surface_from_wlr_surface(wlr_surface); return view_from_wlr_xwayland_surface(xsurface); } - #endif +#endif if (wlr_surface_is_subsurface(wlr_surface)) { struct wlr_subsurface *subsurface = wlr_subsurface_from_wlr_surface(wlr_surface); -- cgit v1.2.3 From 79a45d4a4049e3b9235915cd308ed2995623f833 Mon Sep 17 00:00:00 2001 From: Pascal Pascher Date: Wed, 25 Jul 2018 12:17:10 +0200 Subject: more style fixes, included "sway/config.h" where needed --- sway/tree/view.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 2eff80a8..7cc15ae3 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,6 +3,7 @@ #include #include #include +#include "sway/config.h" #ifdef HAVE_XWAYLAND #include #endif -- cgit v1.2.3 From f95cb9a7c17251c43b1d1058092e0a15d1fe8dd9 Mon Sep 17 00:00:00 2001 From: Pascal Pascher Date: Wed, 25 Jul 2018 13:32:20 +0200 Subject: reverted includes of "sway/config.h" and replaced with "config.h" from meson build --- sway/tree/view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 7cc15ae3..f672417e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,12 +3,12 @@ #include #include #include -#include "sway/config.h" #ifdef HAVE_XWAYLAND #include #endif #include "list.h" #include "log.h" +#include "config.h" #include "sway/criteria.h" #include "sway/commands.h" #include "sway/ipc-server.h" -- cgit v1.2.3 From 384c55c0b465d6b9a9c4cb88d8752435ac5cf708 Mon Sep 17 00:00:00 2001 From: Pascal Pascher Date: Wed, 25 Jul 2018 13:43:21 +0200 Subject: more style fixes, reorder config.h include --- sway/tree/view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index f672417e..beeb8144 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,12 +3,12 @@ #include #include #include +#include "config.h" #ifdef HAVE_XWAYLAND #include #endif #include "list.h" #include "log.h" -#include "config.h" #include "sway/criteria.h" #include "sway/commands.h" #include "sway/ipc-server.h" -- cgit v1.2.3 From 27a20a488465468511de9b2307941ac1bc4db8bf Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 25 Jul 2018 20:56:23 +1000 Subject: Allow containers to be fullscreen --- sway/tree/view.c | 73 ++++---------------------------------------------------- 1 file changed, 4 insertions(+), 69 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index beeb8144..82c3ad4a 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -225,7 +225,7 @@ void view_autoconfigure(struct sway_view *view) { struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - if (view->is_fullscreen) { + if (view->swayc->is_fullscreen) { view->x = output->x; view->y = output->y; view->width = output->width; @@ -233,10 +233,6 @@ void view_autoconfigure(struct sway_view *view) { return; } - if (container_is_floating(view->swayc)) { - return; - } - struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); int other_views = 0; @@ -349,68 +345,6 @@ void view_set_tiled(struct sway_view *view, bool tiled) { } } -void view_set_fullscreen(struct sway_view *view, bool fullscreen) { - if (view->is_fullscreen == fullscreen) { - return; - } - - struct sway_container *workspace = - container_parent(view->swayc, C_WORKSPACE); - - if (view->impl->set_fullscreen) { - view->impl->set_fullscreen(view, fullscreen); - } - - view->is_fullscreen = fullscreen; - - if (fullscreen) { - if (workspace->sway_workspace->fullscreen) { - view_set_fullscreen(workspace->sway_workspace->fullscreen, false); - } - workspace->sway_workspace->fullscreen = view; - view->saved_x = view->x; - view->saved_y = view->y; - view->saved_width = view->width; - view->saved_height = view->height; - view->swayc->saved_x = view->swayc->x; - view->swayc->saved_y = view->swayc->y; - view->swayc->saved_width = view->swayc->width; - view->swayc->saved_height = view->swayc->height; - - struct sway_seat *seat; - struct sway_container *focus, *focus_ws; - wl_list_for_each(seat, &input_manager->seats, link) { - focus = seat_get_focus(seat); - if (focus) { - focus_ws = focus; - if (focus && focus_ws->type != C_WORKSPACE) { - focus_ws = container_parent(focus_ws, C_WORKSPACE); - } - seat_set_focus(seat, view->swayc); - if (focus_ws != workspace) { - seat_set_focus(seat, focus); - } - } - } - } else { - workspace->sway_workspace->fullscreen = NULL; - if (container_is_floating(view->swayc)) { - view->x = view->saved_x; - view->y = view->saved_y; - view->width = view->saved_width; - view->height = view->saved_height; - container_set_geometry_from_floating_view(view->swayc); - } else { - view->swayc->width = view->swayc->saved_width; - view->swayc->height = view->swayc->saved_height; - } - } - - container_end_mouse_operation(view->swayc); - - ipc_event_window(view->swayc, "fullscreen_mode"); -} - void view_close(struct sway_view *view) { if (view->impl->close) { view->impl->close(view); @@ -680,7 +614,7 @@ void view_unmap(struct sway_view *view) { struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); struct sway_container *parent; - if (view->is_fullscreen) { + if (view->swayc->is_fullscreen) { ws->sway_workspace->fullscreen = NULL; parent = container_destroy(view->swayc); @@ -1133,7 +1067,8 @@ bool view_is_visible(struct sway_view *view) { container = container->parent; } // Check view isn't hidden by another fullscreen view - if (workspace->sway_workspace->fullscreen && !view->is_fullscreen) { + if (workspace->sway_workspace->fullscreen && + !container_is_fullscreen_or_child(view->swayc)) { return false; } // Check the workspace is visible -- cgit v1.2.3 From a90f2dbde9866a34e91b242bb06071e471d32eb3 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 25 Jul 2018 23:34:00 +1000 Subject: Refactor view_map * Move workspace selection into separate function * Instead of keeping a `prev_focus` variable, do the check in `should_focus` (ie. views can only take focus if they're mapped into the active workspace) * Fix assign-to-output - it previously set `prev_focus` but should be `target_sibling` * Remove call to `workspace_switch` as we'll only ever focus the view if it's in the active workspace --- sway/tree/view.c | 138 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 75 insertions(+), 63 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 82c3ad4a..fec628e1 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -476,97 +476,112 @@ void view_execute_criteria(struct sway_view *view) { seat_set_focus(seat, prior_focus); } -static bool should_focus(struct sway_view *view) { - // If the view is the only one in the focused workspace, it'll get focus - // regardless of any no_focus criteria. - struct sway_container *parent = view->swayc->parent; +static struct sway_container *select_workspace(struct sway_view *view) { struct sway_seat *seat = input_manager_current_seat(input_manager); - if (parent->type == C_WORKSPACE && seat_get_focus(seat) == parent) { - size_t num_children = parent->children->length + - parent->sway_workspace->floating->children->length; - if (num_children == 1) { - return true; + + // Check if there's any `assign` criteria for the view + list_t *criterias = criteria_for_view(view, + CT_ASSIGN_WORKSPACE | CT_ASSIGN_OUTPUT); + struct sway_container *ws = NULL; + for (int i = 0; i < criterias->length; ++i) { + struct criteria *criteria = criterias->items[i]; + if (criteria->type == CT_ASSIGN_WORKSPACE) { + struct sway_container *ws = workspace_by_name(criteria->target); + if (!ws) { + ws = workspace_create(NULL, criteria->target); + } + break; + } else { + // CT_ASSIGN_OUTPUT + struct sway_container *output = output_by_name(criteria->target); + if (output) { + ws = seat_get_active_child(seat, output); + break; + } } } - - // Check no_focus criteria - list_t *criterias = criteria_for_view(view, CT_NO_FOCUS); - size_t len = criterias->length; list_free(criterias); - return len == 0; -} - -void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { - if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { - return; + if (ws) { + return ws; } + // Check if there's a PID mapping pid_t pid; #ifdef HAVE_XWAYLAND if (view->type == SWAY_VIEW_XWAYLAND) { struct wlr_xwayland_surface *surf = - wlr_xwayland_surface_from_wlr_surface(wlr_surface); + wlr_xwayland_surface_from_wlr_surface(view->surface); pid = surf->pid; } else { struct wl_client *client = - wl_resource_get_client(wlr_surface->resource); + wl_resource_get_client(view->surface->resource); wl_client_get_credentials(client, &pid, NULL, NULL); } #else struct wl_client *client = - wl_resource_get_client(wlr_surface->resource); + wl_resource_get_client(view->surface->resource); wl_client_get_credentials(client, &pid, NULL, NULL); #endif + ws = workspace_for_pid(pid); + if (ws) { + return ws; + } + // Use the focused workspace + ws = seat_get_focus(seat); + if (ws->type != C_WORKSPACE) { + ws = container_parent(ws, C_WORKSPACE); + } + return ws; +} + +static bool should_focus(struct sway_view *view) { struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *target_sibling = - seat_get_focus_inactive(seat, &root_container); - struct sway_container *prev_focus = target_sibling; - struct sway_container *cont = NULL; + struct sway_container *prev_focus = seat_get_focus(seat); + struct sway_container *prev_ws = prev_focus->type == C_WORKSPACE ? + prev_focus : container_parent(prev_focus, C_WORKSPACE); + struct sway_container *map_ws = container_parent(view->swayc, C_WORKSPACE); - // Check if there's any `assign` criteria for the view - list_t *criterias = criteria_for_view(view, - CT_ASSIGN_WORKSPACE | CT_ASSIGN_OUTPUT); - struct sway_container *workspace = NULL; - if (criterias->length) { - struct criteria *criteria = criterias->items[0]; - if (criteria->type == CT_ASSIGN_WORKSPACE) { - workspace = workspace_by_name(criteria->target); - if (!workspace) { - workspace = workspace_create(NULL, criteria->target); - } - prev_focus = target_sibling; - target_sibling = seat_get_focus_inactive(seat, workspace); - } else { - // CT_ASSIGN_OUTPUT - struct sway_container *output = output_by_name(criteria->target); - if (output) { - prev_focus = seat_get_focus_inactive(seat, output); - } + // Views can only take focus if they are mapped into the active workspace + if (prev_ws != map_ws) { + return false; + } + + // If the view is the only one in the focused workspace, it'll get focus + // regardless of any no_focus criteria. + struct sway_container *parent = view->swayc->parent; + if (parent->type == C_WORKSPACE && prev_focus == parent) { + size_t num_children = parent->children->length + + parent->sway_workspace->floating->children->length; + if (num_children == 1) { + return true; } } + + // Check no_focus criteria + list_t *criterias = criteria_for_view(view, CT_NO_FOCUS); + size_t len = criterias->length; list_free(criterias); + return len == 0; +} - if (!workspace) { - workspace = workspace_for_pid(pid); - if (workspace) { - prev_focus = target_sibling; - target_sibling = seat_get_focus_inactive(seat, workspace); - } +void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { + if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { + return; } + view->surface = wlr_surface; + + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *ws = select_workspace(view); + struct sway_container *target_sibling = seat_get_focus_inactive(seat, ws); + // If we're about to launch the view into the floating container, then // launch it as a tiled view in the root of the workspace instead. if (container_is_floating(target_sibling)) { - if (prev_focus == target_sibling) { - prev_focus = target_sibling->parent->parent; - } target_sibling = target_sibling->parent->parent; } - cont = container_view_create(target_sibling, view); - - view->surface = wlr_surface; - view->swayc = cont; + view->swayc = container_view_create(target_sibling, view); view_init_subsurfaces(view, wlr_surface); wl_signal_add(&wlr_surface->events.new_subsurface, @@ -586,11 +601,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { view_set_tiled(view, true); } - if (should_focus(view) && prev_focus == target_sibling) { - input_manager_set_focus(input_manager, cont); - if (workspace) { - workspace_switch(workspace); - } + if (should_focus(view)) { + input_manager_set_focus(input_manager, view->swayc); } view_update_title(view, false); -- cgit v1.2.3 From 6ceb1d33fd9038640f6adf1aabf48b6931dc0fdb Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Fri, 27 Jul 2018 09:21:55 +1000 Subject: Fix assign to workspace --- sway/tree/view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index fec628e1..e641544e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -486,7 +486,7 @@ static struct sway_container *select_workspace(struct sway_view *view) { for (int i = 0; i < criterias->length; ++i) { struct criteria *criteria = criterias->items[i]; if (criteria->type == CT_ASSIGN_WORKSPACE) { - struct sway_container *ws = workspace_by_name(criteria->target); + ws = workspace_by_name(criteria->target); if (!ws) { ws = workspace_create(NULL, criteria->target); } -- cgit v1.2.3 From 08cfba2192f5770d975c5fe70789a81aaee4dc7e Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 26 Jul 2018 18:36:46 +1000 Subject: Allow containers to float Things worth noting: * When a fullscreen view unmaps, the check to unset fullscreen on the workspace has been moved out of view_unmap and into container_destroy, because containers can be fullscreen too * The calls to `container_reap_empty_recursive(workspace)` have been removed from `container_set_floating`. That function reaps upwards so it wouldn't do anything. I'm probably the one who originally added it... * My fix (b14bd1b0b1536039e4f46fe94515c7c44e7afc61) for the tabbed child crash has a side effect where when you close a floating container, focus is not given to the tiled container again. I've removed my fix and removed the call to `send_cursor_motion` from `seat_set_focus_warp`. We should consider calling it from somewhere earlier in the call stack. --- sway/tree/view.c | 53 +---------------------------------------------------- 1 file changed, 1 insertion(+), 52 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index e641544e..253f3001 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -168,55 +168,6 @@ uint32_t view_configure(struct sway_view *view, double lx, double ly, int width, return 0; } -void view_init_floating(struct sway_view *view) { - struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - int min_width, min_height; - int max_width, max_height; - - if (config->floating_minimum_width == -1) { // no minimum - min_width = 0; - } else if (config->floating_minimum_width == 0) { // automatic - min_width = 75; - } else { - min_width = config->floating_minimum_width; - } - - if (config->floating_minimum_height == -1) { // no minimum - min_height = 0; - } else if (config->floating_minimum_height == 0) { // automatic - min_height = 50; - } else { - min_height = config->floating_minimum_height; - } - - if (config->floating_maximum_width == -1) { // no maximum - max_width = INT_MAX; - } else if (config->floating_maximum_width == 0) { // automatic - max_width = ws->width * 0.6666; - } else { - max_width = config->floating_maximum_width; - } - - if (config->floating_maximum_height == -1) { // no maximum - max_height = INT_MAX; - } else if (config->floating_maximum_height == 0) { // automatic - max_height = ws->height * 0.6666; - } else { - max_height = config->floating_maximum_height; - } - - view->width = fmax(min_width, fmin(view->natural_width, max_width)); - view->height = fmax(min_height, fmin(view->natural_height, max_height)); - view->x = ws->x + (ws->width - view->width) / 2; - view->y = ws->y + (ws->height - view->height) / 2; - - // If the view's border is B_NONE then these properties are ignored. - view->border_top = view->border_bottom = true; - view->border_left = view->border_right = true; - - container_set_geometry_from_floating_view(view->swayc); -} - void view_autoconfigure(struct sway_view *view) { if (!sway_assert(view->swayc, "Called view_autoconfigure() on a view without a swayc")) { @@ -626,10 +577,8 @@ void view_unmap(struct sway_view *view) { struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); struct sway_container *parent; - if (view->swayc->is_fullscreen) { - ws->sway_workspace->fullscreen = NULL; + if (container_is_fullscreen_or_child(view->swayc)) { parent = container_destroy(view->swayc); - arrange_windows(ws->parent); } else { parent = container_destroy(view->swayc); -- cgit v1.2.3 From 902a1402ba35be3fbc3c054cd7af5a8bda5f8fd6 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 26 Jul 2018 22:27:42 +1000 Subject: Fix crash when a child of a floating container is in the scratchpad --- sway/tree/view.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 253f3001..8f54cc11 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -999,11 +999,14 @@ void view_update_marks_textures(struct sway_view *view) { } bool view_is_visible(struct sway_view *view) { - if (!view->swayc || view->swayc->destroying || !view->swayc->parent) { + if (!view->swayc || view->swayc->destroying) { return false; } struct sway_container *workspace = container_parent(view->swayc, C_WORKSPACE); + if (!workspace) { + return false; + } // Determine if view is nested inside a floating container which is sticky. // A simple floating view will have this ancestry: // C_VIEW -> floating -> workspace -- cgit v1.2.3 From de86d65627e96cffe77f4abf11c4a0b982326ff9 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 31 Jul 2018 18:41:30 +1000 Subject: 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) --- sway/tree/view.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 8f54cc11..c1207821 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); -- cgit v1.2.3 From 7a59508da467a3b793e355e28ae67ce04633761c Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 31 Jul 2018 19:58:34 +1000 Subject: Close popups when changing focus Also reverts the send frame done changes from the previous commit. --- sway/tree/view.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index c1207821..5d9b625f 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]; -- cgit v1.2.3 From d10ccc1eb144e4de2477398f6b11753f6b7df70b Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 1 Aug 2018 16:23:11 +1000 Subject: 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. --- sway/tree/view.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 8f54cc11..0dbd3812 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; + } +} -- cgit v1.2.3 From 4f8f363dda2495810e419be6e79c3869bb7f17d8 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 13 Jul 2018 17:19:16 +0100 Subject: ipc: add window::title event --- sway/tree/view.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 8f54cc11..7300f207 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, -- cgit v1.2.3 From 317217f2c87aba4463806e211c22296ac9230b6c Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sat, 14 Jul 2018 11:10:36 +0100 Subject: ipc: add window::mark event --- sway/tree/view.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 7300f207..48b39e80 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); -- cgit v1.2.3 From 9339026a31103b453545cf65cd45f345e44d0437 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 2 Aug 2018 21:55:37 +1000 Subject: Fix focus related crashes * seat_set_focus_warp lacked a container NULL check * view mapping code needs to use seat_get_focus_inactive Also, seat_set_focus_warp triggered the wrong IPC event if focus was a workspace, which resulted in swaybar not showing the workspace as active. --- sway/tree/view.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 051b93ce..97318daa 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -496,7 +496,7 @@ static struct sway_container *select_workspace(struct sway_view *view) { } // Use the focused workspace - ws = seat_get_focus(seat); + ws = seat_get_focus_inactive(seat, &root_container); if (ws->type != C_WORKSPACE) { ws = container_parent(ws, C_WORKSPACE); } @@ -505,7 +505,8 @@ static struct sway_container *select_workspace(struct sway_view *view) { static bool should_focus(struct sway_view *view) { struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *prev_focus = seat_get_focus(seat); + struct sway_container *prev_focus = + seat_get_focus_inactive(seat, &root_container); struct sway_container *prev_ws = prev_focus->type == C_WORKSPACE ? prev_focus : container_parent(prev_focus, C_WORKSPACE); struct sway_container *map_ws = container_parent(view->swayc, C_WORKSPACE); -- cgit v1.2.3 From 9aa258d33a9baa42895214da7e82f4568fcb8f76 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 2 Aug 2018 09:05:46 -0400 Subject: Revert "Fix popups" This reverts commit de86d65627e96cffe77f4abf11c4a0b982326ff9. --- sway/tree/view.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 97318daa..27a6a8bd 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -339,16 +339,6 @@ 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); -- cgit v1.2.3 From 8392eae40f17e550338b8b7058d8e9c1a6ad4f78 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 2 Aug 2018 23:30:26 +1000 Subject: Revert "Revert "Fix popups"" This reverts commit 9aa258d33a9baa42895214da7e82f4568fcb8f76. Reverting the revert, so that popups can be fixed. --- sway/tree/view.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 27a6a8bd..97318daa 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -339,6 +339,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); -- cgit v1.2.3