From 3b0c26d149dfe5e05df338692db8255a01f0998d Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 9 May 2018 14:23:20 +1000 Subject: Overhaul criteria implementation The criteria struct now uses properties for each token type rather than the list_t list of tokens. The reason for this is that different token types have different data types: pcre, string and number to name a few. This solution should be more flexible moving forward. A bonus of this is that criteria is now easier to understand when looking at the struct definition. The criteria parser has been rewritten because the previous one didn't support valueless pairs (eg. [class="foo" floating]). Criteria now has types. Types at the moment are CT_COMMAND, CT_ASSIGN_WORKSPACE and CT_ASSIGN_OUTPUT. i3 uses types as well. Previously the assign command was creating a criteria with 'move to workspace ' as its command, but this caused the window to appear briefly on the focused workspace before being moved to the assigned workspace. It now creates the view directly in the assigned workspace. Each view will only execute a given criteria once. This is achieved by storing a list of executed criteria in the view. This is the same strategy used by i3. Escaping now works properly. Previously you could do things like [class="Fire\"fox"] and the stored value would be 'Fire\"fox', but it should be (and now is) 'Fire"fox'. The public functions in criteria.c are now all prefixed with criteria_. Xwayland views now listen to the set_title, set_class and set_window_type events and criteria will be run when these happen. XDG shell has none of these events so it continues to update the title in handle_commit. Each view type's get_prop function has been split into get_string_prop and get_int_prop because some properties like the X11 window ID and window type are numeric. The following new criteria tokens are now supported: * id (X11 window ID) * instance * tiling * workspace --- sway/tree/view.c | 97 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 22 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index afd7eade..7d921e0e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,6 +3,7 @@ #include #include #include +#include "list.h" #include "log.h" #include "sway/criteria.h" #include "sway/commands.h" @@ -19,6 +20,7 @@ void view_init(struct sway_view *view, enum sway_view_type type, const struct sway_view_impl *impl) { view->type = type; view->impl = impl; + view->executed_criteria = create_list(); wl_signal_init(&view->events.unmap); } @@ -31,6 +33,8 @@ void view_destroy(struct sway_view *view) { view_unmap(view); } + list_free(view->executed_criteria); + container_destroy(view->swayc); if (view->impl->destroy) { @@ -41,33 +45,47 @@ void view_destroy(struct sway_view *view) { } const char *view_get_title(struct sway_view *view) { - if (view->impl->get_prop) { - return view->impl->get_prop(view, VIEW_PROP_TITLE); + if (view->impl->get_string_prop) { + return view->impl->get_string_prop(view, VIEW_PROP_TITLE); } return NULL; } const char *view_get_app_id(struct sway_view *view) { - if (view->impl->get_prop) { - return view->impl->get_prop(view, VIEW_PROP_APP_ID); + if (view->impl->get_string_prop) { + return view->impl->get_string_prop(view, VIEW_PROP_APP_ID); } return NULL; } const char *view_get_class(struct sway_view *view) { - if (view->impl->get_prop) { - return view->impl->get_prop(view, VIEW_PROP_CLASS); + if (view->impl->get_string_prop) { + return view->impl->get_string_prop(view, VIEW_PROP_CLASS); } return NULL; } const char *view_get_instance(struct sway_view *view) { - if (view->impl->get_prop) { - return view->impl->get_prop(view, VIEW_PROP_INSTANCE); + if (view->impl->get_string_prop) { + return view->impl->get_string_prop(view, VIEW_PROP_INSTANCE); } return NULL; } +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; +} + +uint32_t view_get_window_type(struct sway_view *view) { + if (view->impl->get_int_prop) { + return view->impl->get_int_prop(view, VIEW_PROP_WINDOW_TYPE); + } + return 0; +} + const char *view_get_type(struct sway_view *view) { switch(view->type) { case SWAY_VIEW_WL_SHELL: @@ -282,19 +300,36 @@ static void view_handle_container_reparent(struct wl_listener *listener, } } -static void view_execute_criteria(struct sway_view *view) { - if (!sway_assert(view->swayc, "cannot run criteria for unmapped view")) { +static bool view_has_executed_criteria(struct sway_view *view, + struct criteria *criteria) { + for (int i = 0; i < view->executed_criteria->length; ++i) { + struct criteria *item = view->executed_criteria->items[i]; + if (item == criteria) { + return true; + } + } + return false; +} + +void view_execute_criteria(struct sway_view *view) { + if (!view->swayc) { return; } struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *prior_workspace = container_parent(view->swayc, C_WORKSPACE); - list_t *criteria = criteria_for(view->swayc); - for (int i = 0; i < criteria->length; i++) { - struct criteria *crit = criteria->items[i]; - wlr_log(L_DEBUG, "for_window '%s' matches new view %p, cmd: '%s'", - crit->crit_raw, view, crit->cmdlist); - struct cmd_results *res = execute_command(crit->cmdlist, NULL); + list_t *criterias = criteria_for_view(view, CT_COMMAND); + for (int i = 0; i < criterias->length; i++) { + struct criteria *criteria = criterias->items[i]; + wlr_log(L_DEBUG, "Checking criteria %s", criteria->raw); + if (view_has_executed_criteria(view, criteria)) { + wlr_log(L_DEBUG, "Criteria already executed"); + continue; + } + wlr_log(L_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", + criteria->raw, view, criteria->cmdlist); + list_add(view->executed_criteria, criteria); + struct cmd_results *res = execute_command(criteria->cmdlist, NULL); if (res->status != CMD_SUCCESS) { wlr_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); } @@ -303,7 +338,7 @@ static void view_execute_criteria(struct sway_view *view) { // so always refocus in-between command lists seat_set_focus(seat, view->swayc); } - list_free(criteria); + list_free(criterias); seat_set_focus(seat, seat_get_focus_inactive(seat, prior_workspace)); } @@ -313,9 +348,26 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { } struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus_inactive(seat, - &root_container); - struct sway_container *cont = container_view_create(focus, view); + struct sway_container *focus = seat_get_focus(seat); + struct sway_container *cont = NULL; + + // Check if there's any `assign` criteria for the view + list_t *criterias = criteria_for_view(view, + CT_ASSIGN_WORKSPACE | CT_ASSIGN_OUTPUT); + if (criterias->length) { + struct criteria *criteria = criterias->items[0]; + if (criteria->type == CT_ASSIGN_WORKSPACE) { + struct sway_container *workspace = workspace_by_name(criteria->target); + if (!workspace) { + workspace = workspace_create(NULL, criteria->target); + } + focus = seat_get_focus_inactive(seat, workspace); + } else { + // TODO: CT_ASSIGN_OUTPUT + } + } + free(criterias); + cont = container_view_create(focus, view); view->surface = wlr_surface; view->swayc = cont; @@ -333,10 +385,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { arrange_children_of(cont->parent); input_manager_set_focus(input_manager, cont); + view_update_title(view, false); + view_execute_criteria(view); + container_damage_whole(cont); view_handle_container_reparent(&view->container_reparent, NULL); - - view_execute_criteria(view); } void view_unmap(struct sway_view *view) { -- cgit v1.2.3 From 935bda0f336bb9ca45a7fb96d7ed5f08ef04432f Mon Sep 17 00:00:00 2001 From: Dudemanguy911 Date: Fri, 11 May 2018 01:20:20 +0000 Subject: fix crash on fullscreen toggle --- sway/tree/view.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index afd7eade..424c1084 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -163,13 +163,15 @@ void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen) { struct sway_container *focus, *focus_ws; wl_list_for_each(seat, &input_manager->seats, link) { focus = seat_get_focus(seat); - focus_ws = focus; - if (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); + 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 { -- cgit v1.2.3 From 94e42f985778ce402b4c47bf8c38ee4233b6204d Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Fri, 11 May 2018 14:58:24 +1000 Subject: Implement __focused__ criteria --- sway/tree/view.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 7d921e0e..ca84d82e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -79,6 +79,13 @@ uint32_t view_get_x11_window_id(struct sway_view *view) { return 0; } +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); + } + return NULL; +} + uint32_t view_get_window_type(struct sway_view *view) { if (view->impl->get_int_prop) { return view->impl->get_int_prop(view, VIEW_PROP_WINDOW_TYPE); -- cgit v1.2.3 From ac0e62584f6101277b76622a7274866cd50f615c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 12 May 2018 08:52:48 -0400 Subject: Revert "Merge pull request #1953 from RyanDwyer/criteria-focused" This reverts commit 2511adffc29996b64d01d85b3de31de9a2af9096, reversing changes made to 3e1bf721c69cb6df70c3dc3d3d4933e987339676. --- sway/tree/view.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 3b3b6eaf..7431ac06 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -79,13 +79,6 @@ uint32_t view_get_x11_window_id(struct sway_view *view) { return 0; } -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); - } - return NULL; -} - uint32_t view_get_window_type(struct sway_view *view) { if (view->impl->get_int_prop) { return view->impl->get_int_prop(view, VIEW_PROP_WINDOW_TYPE); -- cgit v1.2.3 From 32a572cecfd0f6072a78ce0a381a2f8365f9010a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 12 May 2018 08:52:54 -0400 Subject: Revert "Merge pull request #1943 from RyanDwyer/criteria-improvements" This reverts commit 3e1bf721c69cb6df70c3dc3d3d4933e987339676, reversing changes made to 2217518bd554d0f11dafa7ec4e8f35f2e4762fbd. --- sway/tree/view.c | 97 +++++++++++++------------------------------------------- 1 file changed, 22 insertions(+), 75 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 7431ac06..424c1084 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,7 +3,6 @@ #include #include #include -#include "list.h" #include "log.h" #include "sway/criteria.h" #include "sway/commands.h" @@ -20,7 +19,6 @@ void view_init(struct sway_view *view, enum sway_view_type type, const struct sway_view_impl *impl) { view->type = type; view->impl = impl; - view->executed_criteria = create_list(); wl_signal_init(&view->events.unmap); } @@ -33,8 +31,6 @@ void view_destroy(struct sway_view *view) { view_unmap(view); } - list_free(view->executed_criteria); - container_destroy(view->swayc); if (view->impl->destroy) { @@ -45,47 +41,33 @@ void view_destroy(struct sway_view *view) { } const char *view_get_title(struct sway_view *view) { - if (view->impl->get_string_prop) { - return view->impl->get_string_prop(view, VIEW_PROP_TITLE); + if (view->impl->get_prop) { + return view->impl->get_prop(view, VIEW_PROP_TITLE); } return NULL; } const char *view_get_app_id(struct sway_view *view) { - if (view->impl->get_string_prop) { - return view->impl->get_string_prop(view, VIEW_PROP_APP_ID); + if (view->impl->get_prop) { + return view->impl->get_prop(view, VIEW_PROP_APP_ID); } return NULL; } const char *view_get_class(struct sway_view *view) { - if (view->impl->get_string_prop) { - return view->impl->get_string_prop(view, VIEW_PROP_CLASS); + if (view->impl->get_prop) { + return view->impl->get_prop(view, VIEW_PROP_CLASS); } return NULL; } const char *view_get_instance(struct sway_view *view) { - if (view->impl->get_string_prop) { - return view->impl->get_string_prop(view, VIEW_PROP_INSTANCE); + if (view->impl->get_prop) { + return view->impl->get_prop(view, VIEW_PROP_INSTANCE); } return NULL; } -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; -} - -uint32_t view_get_window_type(struct sway_view *view) { - if (view->impl->get_int_prop) { - return view->impl->get_int_prop(view, VIEW_PROP_WINDOW_TYPE); - } - return 0; -} - const char *view_get_type(struct sway_view *view) { switch(view->type) { case SWAY_VIEW_WL_SHELL: @@ -302,36 +284,19 @@ static void view_handle_container_reparent(struct wl_listener *listener, } } -static bool view_has_executed_criteria(struct sway_view *view, - struct criteria *criteria) { - for (int i = 0; i < view->executed_criteria->length; ++i) { - struct criteria *item = view->executed_criteria->items[i]; - if (item == criteria) { - return true; - } - } - return false; -} - -void view_execute_criteria(struct sway_view *view) { - if (!view->swayc) { +static void view_execute_criteria(struct sway_view *view) { + if (!sway_assert(view->swayc, "cannot run criteria for unmapped view")) { return; } struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *prior_workspace = container_parent(view->swayc, C_WORKSPACE); - list_t *criterias = criteria_for_view(view, CT_COMMAND); - for (int i = 0; i < criterias->length; i++) { - struct criteria *criteria = criterias->items[i]; - wlr_log(L_DEBUG, "Checking criteria %s", criteria->raw); - if (view_has_executed_criteria(view, criteria)) { - wlr_log(L_DEBUG, "Criteria already executed"); - continue; - } - wlr_log(L_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", - criteria->raw, view, criteria->cmdlist); - list_add(view->executed_criteria, criteria); - struct cmd_results *res = execute_command(criteria->cmdlist, NULL); + list_t *criteria = criteria_for(view->swayc); + for (int i = 0; i < criteria->length; i++) { + struct criteria *crit = criteria->items[i]; + wlr_log(L_DEBUG, "for_window '%s' matches new view %p, cmd: '%s'", + crit->crit_raw, view, crit->cmdlist); + struct cmd_results *res = execute_command(crit->cmdlist, NULL); if (res->status != CMD_SUCCESS) { wlr_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); } @@ -340,7 +305,7 @@ void view_execute_criteria(struct sway_view *view) { // so always refocus in-between command lists seat_set_focus(seat, view->swayc); } - list_free(criterias); + list_free(criteria); seat_set_focus(seat, seat_get_focus_inactive(seat, prior_workspace)); } @@ -350,26 +315,9 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { } struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); - struct sway_container *cont = NULL; - - // Check if there's any `assign` criteria for the view - list_t *criterias = criteria_for_view(view, - CT_ASSIGN_WORKSPACE | CT_ASSIGN_OUTPUT); - if (criterias->length) { - struct criteria *criteria = criterias->items[0]; - if (criteria->type == CT_ASSIGN_WORKSPACE) { - struct sway_container *workspace = workspace_by_name(criteria->target); - if (!workspace) { - workspace = workspace_create(NULL, criteria->target); - } - focus = seat_get_focus_inactive(seat, workspace); - } else { - // TODO: CT_ASSIGN_OUTPUT - } - } - free(criterias); - cont = container_view_create(focus, view); + struct sway_container *focus = seat_get_focus_inactive(seat, + &root_container); + struct sway_container *cont = container_view_create(focus, view); view->surface = wlr_surface; view->swayc = cont; @@ -387,11 +335,10 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { arrange_children_of(cont->parent); input_manager_set_focus(input_manager, cont); - view_update_title(view, false); - view_execute_criteria(view); - container_damage_whole(cont); view_handle_container_reparent(&view->container_reparent, NULL); + + view_execute_criteria(view); } void view_unmap(struct sway_view *view) { -- cgit v1.2.3