mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -05:00 
			
		
		
		
	desktop: refactor desktop_cycle_view()
...in preparation for using common window-rule criteria with osd.c No functional change intended. Related-to #1454
This commit is contained in:
		
							parent
							
								
									6a35e8e78c
								
							
						
					
					
						commit
						777e6bb868
					
				
					 3 changed files with 77 additions and 90 deletions
				
			
		| 
						 | 
				
			
			@ -321,6 +321,15 @@ 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);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Same as `view_next()` except that they iterate one whole cycle rather than
 | 
			
		||||
 * stopping at the list-head
 | 
			
		||||
 */
 | 
			
		||||
struct view *view_next_no_head_stop(struct wl_list *head, struct view *from,
 | 
			
		||||
	enum lab_view_criteria criteria);
 | 
			
		||||
struct view *view_prev_no_head_stop(struct wl_list *head, struct view *from,
 | 
			
		||||
	enum lab_view_criteria criteria);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * view_array_append() - Append views that match criteria to array
 | 
			
		||||
 * @server: server context
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										116
									
								
								src/desktop.c
									
										
									
									
									
								
							
							
						
						
									
										116
									
								
								src/desktop.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -106,109 +106,45 @@ desktop_focus_view_or_surface(struct seat *seat, struct view *view,
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct wl_list *
 | 
			
		||||
get_prev_item(struct wl_list *item)
 | 
			
		||||
{
 | 
			
		||||
	return item->prev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct wl_list *
 | 
			
		||||
get_next_item(struct wl_list *item)
 | 
			
		||||
{
 | 
			
		||||
	return item->next;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct view *
 | 
			
		||||
first_view(struct server *server)
 | 
			
		||||
{
 | 
			
		||||
	struct wlr_scene_node *node;
 | 
			
		||||
	struct wl_list *list_head =
 | 
			
		||||
		&server->workspace_current->tree->children;
 | 
			
		||||
	wl_list_for_each_reverse(node, list_head, link) {
 | 
			
		||||
		if (!node->data) {
 | 
			
		||||
			/* We found some non-view, most likely the region overlay */
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		struct view *view = node_view_from_node(node);
 | 
			
		||||
		if (view_is_focusable(view)) {
 | 
			
		||||
			return view;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct view *
 | 
			
		||||
desktop_cycle_view(struct server *server, struct view *start_view,
 | 
			
		||||
		enum lab_cycle_dir dir)
 | 
			
		||||
{
 | 
			
		||||
	/* Make sure to have all nodes in their actual ordering */
 | 
			
		||||
	osd_preview_restore(server);
 | 
			
		||||
 | 
			
		||||
	struct view *(*iter)(struct wl_list *head, struct view *view,
 | 
			
		||||
		enum lab_view_criteria criteria);
 | 
			
		||||
	bool forwards = dir == LAB_CYCLE_DIR_FORWARD;
 | 
			
		||||
	iter = forwards ? view_next_no_head_stop : view_prev_no_head_stop;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Views are listed in stacking order, topmost first.  Usually
 | 
			
		||||
	 * the topmost view is already focused, so we pre-select the
 | 
			
		||||
	 * view second from the top:
 | 
			
		||||
	 * TODO: These criteria are the same as in display_osd() in osd.c
 | 
			
		||||
	 * for the time being.
 | 
			
		||||
	 *
 | 
			
		||||
	 * A future improvement could be to make this configurable for example
 | 
			
		||||
	 * in rc.xml and then use rc.cycle_view_criteria (or whatever) both
 | 
			
		||||
	 * here and in the osd.c window-switcher code
 | 
			
		||||
	 */
 | 
			
		||||
	enum lab_view_criteria criteria = LAB_VIEW_CRITERIA_CURRENT_WORKSPACE
 | 
			
		||||
		| LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP
 | 
			
		||||
		| LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Views are listed in stacking order, topmost first.  Usually the
 | 
			
		||||
	 * topmost view is already focused, so when iterating in the forward
 | 
			
		||||
	 * direction we pre-select the view second from the top:
 | 
			
		||||
	 *
 | 
			
		||||
	 *   View #1 (on top, currently focused)
 | 
			
		||||
	 *   View #2 (pre-selected)
 | 
			
		||||
	 *   View #3
 | 
			
		||||
	 *   ...
 | 
			
		||||
	 *
 | 
			
		||||
	 * This assumption doesn't always hold with XWayland views,
 | 
			
		||||
	 * where a main application window may be focused but an
 | 
			
		||||
	 * focusable sub-view (e.g. an about dialog) may still be on
 | 
			
		||||
	 * top of it.  In that case, we pre-select the sub-view:
 | 
			
		||||
	 *
 | 
			
		||||
	 *   Sub-view of #1 (on top, pre-selected)
 | 
			
		||||
	 *   Main view #1 (currently focused)
 | 
			
		||||
	 *   Main view #2
 | 
			
		||||
	 *   ...
 | 
			
		||||
	 *
 | 
			
		||||
	 * The general rule is:
 | 
			
		||||
	 *
 | 
			
		||||
	 *   - Pre-select the top view if NOT already focused
 | 
			
		||||
	 *   - Otherwise select the view second from the top
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	/* Make sure to have all nodes in their actual ordering */
 | 
			
		||||
	osd_preview_restore(server);
 | 
			
		||||
 | 
			
		||||
	if (!start_view) {
 | 
			
		||||
		start_view = first_view(server);
 | 
			
		||||
		if (!start_view || start_view != server->active_view) {
 | 
			
		||||
			return start_view;  /* may be NULL */
 | 
			
		||||
		}
 | 
			
		||||
	if (!start_view && forwards) {
 | 
			
		||||
		start_view = iter(&server->views, NULL, criteria);
 | 
			
		||||
	}
 | 
			
		||||
	struct view *view = start_view;
 | 
			
		||||
	struct wlr_scene_node *node = &view->scene_tree->node;
 | 
			
		||||
 | 
			
		||||
	assert(node->parent);
 | 
			
		||||
	struct wl_list *list_head = &node->parent->children;
 | 
			
		||||
	struct wl_list *list_item = &node->link;
 | 
			
		||||
	struct wl_list *(*iter)(struct wl_list *list);
 | 
			
		||||
 | 
			
		||||
	/* Scene nodes are ordered like last node == displayed topmost */
 | 
			
		||||
	iter = dir == LAB_CYCLE_DIR_FORWARD ? get_prev_item : get_next_item;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		list_item = iter(list_item);
 | 
			
		||||
		if (list_item == list_head) {
 | 
			
		||||
			/* Start / End of list reached. Roll over */
 | 
			
		||||
			list_item = iter(list_item);
 | 
			
		||||
		}
 | 
			
		||||
		node = wl_container_of(list_item, node, link);
 | 
			
		||||
		if (!node->data) {
 | 
			
		||||
			/* We found some non-view, most likely the region overlay */
 | 
			
		||||
			view = NULL;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		view = node_view_from_node(node);
 | 
			
		||||
 | 
			
		||||
		enum property skip = window_rules_get_property(view, "skipWindowSwitcher");
 | 
			
		||||
		if (view_is_focusable(view) && skip != LAB_PROP_TRUE) {
 | 
			
		||||
			return view;
 | 
			
		||||
		}
 | 
			
		||||
	} while (view != start_view);
 | 
			
		||||
 | 
			
		||||
	/* No focusable views found, including the one we started with */
 | 
			
		||||
	return NULL;
 | 
			
		||||
	return iter(&server->views, start_view, criteria);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct view *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										42
									
								
								src/view.c
									
										
									
									
									
								
							
							
						
						
									
										42
									
								
								src/view.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -137,6 +137,48 @@ view_next(struct wl_list *head, struct view *view, enum lab_view_criteria criter
 | 
			
		|||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct view *
 | 
			
		||||
view_next_no_head_stop(struct wl_list *head, struct view *from,
 | 
			
		||||
		enum lab_view_criteria criteria)
 | 
			
		||||
{
 | 
			
		||||
	assert(head);
 | 
			
		||||
 | 
			
		||||
	struct wl_list *elm = from ? &from->link : head;
 | 
			
		||||
 | 
			
		||||
	struct wl_list *end = elm;
 | 
			
		||||
	for (elm = elm->next; elm != end; elm = elm->next) {
 | 
			
		||||
		if (elm == head) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		struct view *view = wl_container_of(elm, view, link);
 | 
			
		||||
		if (matches_criteria(view, criteria)) {
 | 
			
		||||
			return view;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return from;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct view *
 | 
			
		||||
view_prev_no_head_stop(struct wl_list *head, struct view *from,
 | 
			
		||||
		enum lab_view_criteria criteria)
 | 
			
		||||
{
 | 
			
		||||
	assert(head);
 | 
			
		||||
 | 
			
		||||
	struct wl_list *elm = from ? &from->link : head;
 | 
			
		||||
 | 
			
		||||
	struct wl_list *end = elm;
 | 
			
		||||
	for (elm = elm->prev; elm != end; elm = elm->prev) {
 | 
			
		||||
		if (elm == head) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		struct view *view = wl_container_of(elm, view, link);
 | 
			
		||||
		if (matches_criteria(view, criteria)) {
 | 
			
		||||
			return view;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return from;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
view_array_append(struct server *server, struct wl_array *views,
 | 
			
		||||
		enum lab_view_criteria criteria)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue