diff --git a/include/view.h b/include/view.h index bffdea07..19b04939 100644 --- a/include/view.h +++ b/include/view.h @@ -381,11 +381,27 @@ bool view_matches_query(struct view *view, struct view_query *query); * printf("%s\n", view_get_string_prop(view, "app_id")); * } */ -#define for_each_view(view, head, criteria) \ - for (view = view_next(head, NULL, criteria); \ - view; \ +#define for_each_view(view, head, criteria) \ + for (view = view_next(head, NULL, criteria); \ + view; \ view = view_next(head, view, criteria)) +/** + * for_each_view_reverse() - iterate over all views which match criteria + * @view: Iterator. + * @head: Head of list to iterate over. + * @criteria: Criteria to match against. + * Example: + * struct view *view; + * for_each_view_reverse(view, &server->views, LAB_VIEW_CRITERIA_NONE) { + * printf("%s\n", view_get_string_prop(view, "app_id")); + * } + */ +#define for_each_view_reverse(view, head, criteria) \ + for (view = view_prev(head, NULL, criteria); \ + view; \ + view = view_prev(head, view, criteria)) + /** * view_next() - Get next view which matches criteria. * @head: Head of list to iterate over. @@ -398,6 +414,18 @@ bool view_matches_query(struct view *view, struct view_query *query); struct view *view_next(struct wl_list *head, struct view *view, enum lab_view_criteria criteria); +/** + * view_prev() - Get previous view which matches criteria. + * @head: Head of list to iterate over. + * @view: Current view from which to find the previous one. If NULL is provided + * as the view argument, the end of the list will be used. + * @criteria: Criteria to match against. + * + * Returns NULL if there are no views matching the criteria. + */ +struct view *view_prev(struct wl_list *head, struct view *view, + enum lab_view_criteria criteria); + /* * Same as `view_next()` except that they iterate one whole cycle rather than * stopping at the list-head diff --git a/src/view.c b/src/view.c index d64fddad..74a75286 100644 --- a/src/view.c +++ b/src/view.c @@ -269,6 +269,22 @@ view_next(struct wl_list *head, struct view *view, enum lab_view_criteria criter return NULL; } +struct view * +view_prev(struct wl_list *head, struct view *view, enum lab_view_criteria criteria) +{ + assert(head); + + struct wl_list *elm = view ? &view->link : head; + + for (elm = elm->prev; elm != head; elm = elm->prev) { + view = wl_container_of(elm, view, link); + if (matches_criteria(view, criteria)) { + return view; + } + } + return NULL; +} + struct view * view_next_no_head_stop(struct wl_list *head, struct view *from, enum lab_view_criteria criteria)