mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -05:00 
			
		
		
		
	view: refactor view_next()
This commit is contained in:
		
							parent
							
								
									b8fd4fed53
								
							
						
					
					
						commit
						afaf78aa72
					
				
					 7 changed files with 50 additions and 65 deletions
				
			
		| 
						 | 
					@ -128,6 +128,7 @@ struct view {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool mapped;
 | 
						bool mapped;
 | 
				
			||||||
	bool been_mapped;
 | 
						bool been_mapped;
 | 
				
			||||||
 | 
						bool minimized;
 | 
				
			||||||
	int x, y, w, h;
 | 
						int x, y, w, h;
 | 
				
			||||||
	bool show_server_side_deco;
 | 
						bool show_server_side_deco;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,8 +179,7 @@ struct wlr_box view_get_surface_geometry(struct view *view);
 | 
				
			||||||
struct wlr_box view_geometry(struct view *view);
 | 
					struct wlr_box view_geometry(struct view *view);
 | 
				
			||||||
void view_resize(struct view *view, struct wlr_box geo);
 | 
					void view_resize(struct view *view, struct wlr_box geo);
 | 
				
			||||||
void view_focus(struct view *view);
 | 
					void view_focus(struct view *view);
 | 
				
			||||||
struct view *view_front_toplevel(struct server *server);
 | 
					struct view *view_next(struct view *current);
 | 
				
			||||||
struct view *next_toplevel(struct view *current);
 | 
					 | 
				
			||||||
bool view_hasfocus(struct view *view);
 | 
					bool view_hasfocus(struct view *view);
 | 
				
			||||||
struct view *view_at(struct server *server, double lx, double ly,
 | 
					struct view *view_at(struct server *server, double lx, double ly,
 | 
				
			||||||
		     struct wlr_surface **surface, double *sx, double *sy,
 | 
							     struct wlr_surface **surface, double *sx, double *sy,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ void action(struct server *server, struct keybind *keybind)
 | 
				
			||||||
	if (!strcasecmp(keybind->action, "Exit")) {
 | 
						if (!strcasecmp(keybind->action, "Exit")) {
 | 
				
			||||||
		wl_display_terminate(server->wl_display);
 | 
							wl_display_terminate(server->wl_display);
 | 
				
			||||||
	} else if (!strcasecmp(keybind->action, "NextWindow")) {
 | 
						} else if (!strcasecmp(keybind->action, "NextWindow")) {
 | 
				
			||||||
		server->cycle_view = next_toplevel(view_front_toplevel(server));
 | 
							server->cycle_view = view_next(server->cycle_view);
 | 
				
			||||||
	} else if (!strcasecmp(keybind->action, "Execute")) {
 | 
						} else if (!strcasecmp(keybind->action, "Execute")) {
 | 
				
			||||||
		spawn_async_no_shell(keybind->command);
 | 
							spawn_async_no_shell(keybind->command);
 | 
				
			||||||
	} else if (!strcasecmp(keybind->action, "debug-views")) {
 | 
						} else if (!strcasecmp(keybind->action, "debug-views")) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,6 +71,10 @@ static void show_one_xwl_view(struct view *view)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void dbg_show_one_view(struct view *view)
 | 
					void dbg_show_one_view(struct view *view)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (!view->surface)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						if (!view->mapped && !view->minimized)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	if (view->type == LAB_XDG_SHELL_VIEW)
 | 
						if (view->type == LAB_XDG_SHELL_VIEW)
 | 
				
			||||||
		show_one_xdg_view(view);
 | 
							show_one_xdg_view(view);
 | 
				
			||||||
	else if (view->type == LAB_XWAYLAND_VIEW)
 | 
						else if (view->type == LAB_XWAYLAND_VIEW)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,7 @@ static void keyboard_handle_key(struct wl_listener *listener, void *data)
 | 
				
			||||||
			server->cycle_view = NULL;
 | 
								server->cycle_view = NULL;
 | 
				
			||||||
		} else if (event->state == WLR_KEY_PRESSED) {
 | 
							} else if (event->state == WLR_KEY_PRESSED) {
 | 
				
			||||||
			/* cycle to next */
 | 
								/* cycle to next */
 | 
				
			||||||
			server->cycle_view = next_toplevel(server->cycle_view);
 | 
								server->cycle_view = view_next(server->cycle_view);
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										97
									
								
								src/view.c
									
										
									
									
									
								
							
							
						
						
									
										97
									
								
								src/view.c
									
										
									
									
									
								
							| 
						 | 
					@ -1,19 +1,6 @@
 | 
				
			||||||
#include "labwc.h"
 | 
					#include "labwc.h"
 | 
				
			||||||
#include "common/bug-on.h"
 | 
					#include "common/bug-on.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool is_toplevel(struct view *view)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!view)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	switch (view->type) {
 | 
					 | 
				
			||||||
	case LAB_XDG_SHELL_VIEW:
 | 
					 | 
				
			||||||
		return view->xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL;
 | 
					 | 
				
			||||||
	case LAB_XWAYLAND_VIEW:
 | 
					 | 
				
			||||||
		return view->xwayland_surface->parent == NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void view_init_position(struct view *view)
 | 
					void view_init_position(struct view *view)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* If surface already has a 'desired' position, don't touch it */
 | 
						/* If surface already has a 'desired' position, don't touch it */
 | 
				
			||||||
| 
						 | 
					@ -112,39 +99,6 @@ bool view_hasfocus(struct view *view)
 | 
				
			||||||
	return (view->surface == seat->keyboard_state.focused_surface);
 | 
						return (view->surface == seat->keyboard_state.focused_surface);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct wlr_xwayland_surface *top_parent(struct view *view)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct wlr_xwayland_surface *s = view->xwayland_surface;
 | 
					 | 
				
			||||||
	while (s->parent)
 | 
					 | 
				
			||||||
		s = s->parent;
 | 
					 | 
				
			||||||
	return s;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void move_xwayland_decendants_to_front(struct view *parent)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!parent || parent->type != LAB_XWAYLAND_VIEW)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	struct view *view, *next;
 | 
					 | 
				
			||||||
	wl_list_for_each_reverse_safe(view, next, &parent->server->views, link)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		/* need to stop here, otherwise loops keeps going forever */
 | 
					 | 
				
			||||||
		if (view == parent)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		if (view->type != LAB_XWAYLAND_VIEW)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		if (!view->mapped)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		if (top_parent(view) != parent->xwayland_surface)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		move_to_front(view);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Note that if 'view' is not a toplevel view, the 'front' toplevel view
 | 
					 | 
				
			||||||
 * will be focussed on; but if 'view' is a toplevel view, the 'next'
 | 
					 | 
				
			||||||
 * will be focussed on.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void view_focus(struct view *view)
 | 
					void view_focus(struct view *view)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Note: this function only deals with keyboard focus. */
 | 
						/* Note: this function only deals with keyboard focus. */
 | 
				
			||||||
| 
						 | 
					@ -183,27 +137,56 @@ void view_focus(struct view *view)
 | 
				
			||||||
				       keyboard->num_keycodes,
 | 
									       keyboard->num_keycodes,
 | 
				
			||||||
				       &keyboard->modifiers);
 | 
									       &keyboard->modifiers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	move_xwayland_decendants_to_front(view);
 | 
						/* TODO: move xwayland decendants to front */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct view *view_front_toplevel(struct server *server)
 | 
					static struct view *first_view(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct view *view;
 | 
						struct view *view;
 | 
				
			||||||
	wl_list_for_each (view, &server->views, link) {
 | 
						view = wl_container_of(server.views.next, view, link);
 | 
				
			||||||
		if (is_toplevel(view))
 | 
						return view;
 | 
				
			||||||
			return view;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct view *next_toplevel(struct view *current)
 | 
					/*
 | 
				
			||||||
 | 
					 * Some xwayland apps produce unmapped surfaces on startup and also leave
 | 
				
			||||||
 | 
					 * some unmapped surfaces kicking around on 'close' (for example * leafpad's
 | 
				
			||||||
 | 
					 * "about" dialogue). Whilst this is not normally a problem, we have to be
 | 
				
			||||||
 | 
					 * careful when cycling between views. The only view's we should focus are
 | 
				
			||||||
 | 
					 * those that are already mapped and those that have been minimized.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static bool isfocusable(struct view *view)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!current)
 | 
						/* filter out those xwayland surfaces that have never been mapped */
 | 
				
			||||||
 | 
						if (!view->surface)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						return (view->mapped || view->minimized);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int has_focusable_view(struct wl_list *wl_list)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct view *view;
 | 
				
			||||||
 | 
						wl_list_for_each (view, wl_list, link) {
 | 
				
			||||||
 | 
							if (isfocusable(view))
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Return next view. If NULL provided, return second view from front.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					/* TODO: rename function */
 | 
				
			||||||
 | 
					struct view *view_next(struct view *current)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!has_focusable_view(&server.views))
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	struct view *view = current;
 | 
					
 | 
				
			||||||
 | 
						struct view *view = current ? current : first_view();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Replacement for wl_list_for_each_from() */
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		view = wl_container_of(view->link.next, view, link);
 | 
							view = wl_container_of(view->link.next, view, link);
 | 
				
			||||||
	} while (!is_toplevel(view));
 | 
						} while (&view->link == &server.views || !isfocusable(view));
 | 
				
			||||||
	return view;
 | 
						return view;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,7 +148,7 @@ static void xdg_toplevel_view_unmap(struct view *view)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	view->mapped = false;
 | 
						view->mapped = false;
 | 
				
			||||||
	wl_list_remove(&view->commit.link);
 | 
						wl_list_remove(&view->commit.link);
 | 
				
			||||||
	view_focus(next_toplevel(view));
 | 
						view_focus(view_next(view));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct view_impl xdg_toplevel_view_impl = {
 | 
					static const struct view_impl xdg_toplevel_view_impl = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,8 +57,6 @@ static void _close(struct view *view)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool want_ssd(struct view *view)
 | 
					static bool want_ssd(struct view *view)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (view->xwayland_surface->override_redirect)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	if (view->xwayland_surface->decorations !=
 | 
						if (view->xwayland_surface->decorations !=
 | 
				
			||||||
	    WLR_XWAYLAND_SURFACE_DECORATIONS_ALL)
 | 
						    WLR_XWAYLAND_SURFACE_DECORATIONS_ALL)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
| 
						 | 
					@ -89,7 +87,7 @@ static void unmap(struct view *view)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	view->mapped = false;
 | 
						view->mapped = false;
 | 
				
			||||||
	wl_list_remove(&view->commit.link);
 | 
						wl_list_remove(&view->commit.link);
 | 
				
			||||||
	view_focus(next_toplevel(view));
 | 
						view_focus(view_next(view));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct view_impl xwl_view_impl = {
 | 
					static const struct view_impl xwl_view_impl = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue