criteria: add view-only matcher for swallows

The swallow walker matches against a view that has not yet been
attached to a container. Factor the view-intrinsic checks out of
criteria_matches_view and expose them as
criteria_matches_view_unmapped.
This commit is contained in:
codegax 2026-04-26 11:30:00 -06:00
parent 850e50b9b7
commit 83d6fef24e
2 changed files with 51 additions and 20 deletions

View file

@ -83,6 +83,18 @@ struct criteria *criteria_parse(char *raw, char **error);
*/
list_t *criteria_for_view(struct sway_view *view, enum criteria_type types);
/**
* Match a criteria against a view without requiring view->container to be
* set. Used by append_layout's swallow matching, which runs before a view
* is attached to a container in the tree. Only view-intrinsic fields are
* considered: title, shell, app_id, sandbox_*, tag, pid, and (when xwayland
* is enabled) class, instance, window_role, window_type, X11 id. Criteria
* fields that depend on container state (con_mark, con_id, floating, tiling,
* workspace, urgent) are ignored.
*/
bool criteria_matches_view_unmapped(struct criteria *criteria,
struct sway_view *view);
/**
* Compile a list of containers matching the given criteria.
*/

View file

@ -190,16 +190,9 @@ static bool criteria_matches_container(struct criteria *criteria,
return true;
}
static bool criteria_matches_view(struct criteria *criteria,
struct sway_view *view) {
struct sway_seat *seat = input_manager_current_seat();
struct sway_container *focus = seat_get_focused_container(seat);
struct sway_view *focused = focus ? focus->view : NULL;
if (!view->container) {
return false;
}
// View-intrinsic checks; does not require view->container.
static bool match_view_intrinsic(struct criteria *criteria,
struct sway_view *view, struct sway_view *focused) {
if (criteria->title) {
const char *title = view_get_title(view);
if (!title) {
@ -340,10 +333,6 @@ static bool criteria_matches_view(struct criteria *criteria,
}
}
if (!criteria_matches_container(criteria, view->container)) {
return false;
}
#if WLR_HAS_XWAYLAND
if (criteria->id) { // X11 window ID
uint32_t x11_window_id = view_get_x11_window_id(view);
@ -419,6 +408,42 @@ static bool criteria_matches_view(struct criteria *criteria,
}
#endif
if (criteria->pid) {
if (criteria->pid != view->pid) {
return false;
}
}
return true;
}
bool criteria_matches_view_unmapped(struct criteria *criteria,
struct sway_view *view) {
struct sway_seat *seat = input_manager_current_seat();
struct sway_container *focus = seat_get_focused_container(seat);
struct sway_view *focused = focus ? focus->view : NULL;
return match_view_intrinsic(criteria, view, focused);
}
static bool criteria_matches_view(struct criteria *criteria,
struct sway_view *view) {
struct sway_seat *seat = input_manager_current_seat();
struct sway_container *focus = seat_get_focused_container(seat);
struct sway_view *focused = focus ? focus->view : NULL;
if (!view->container) {
return false;
}
if (!match_view_intrinsic(criteria, view, focused)) {
return false;
}
if (!criteria_matches_container(criteria, view->container)) {
return false;
}
if (criteria->floating) {
if (!container_is_floating(view->container)) {
return false;
@ -471,12 +496,6 @@ static bool criteria_matches_view(struct criteria *criteria,
}
}
if (criteria->pid) {
if (criteria->pid != view->pid) {
return false;
}
}
return true;
}