[PATCH weston 06/11] shell: Organize workspace containers by output

Pekka Paalanen ppaalanen at gmail.com
Mon Jan 28 01:33:11 PST 2013


Hi Jonas,

this raised a couple of thoughts, inline below.


On Sat, 26 Jan 2013 15:33:36 +0100
Jonas Ådahl <jadahl at gmail.com> wrote:

> Instead of having one global workspace container, have one container per
> output. This means that every output will have its own set of workspaces
> with its own workspace state.
> 
> New surfaces are added to the current workspace on the container of the
> output the surface was positioned at.
> 
> The workspace manager interface is currently limited to only represent
> the container of the first output. All events and requests are handleded
> as if there was only one container.
> 
> The keyboard bindings for changing workspaces are updated to change the
> state of the container of the output where the pointer is on. If no
> pointer exists, the workspace changing bindings are no-ops.
> 
> Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
> ---
>  src/shell.c |  367 +++++++++++++++++++++++++++++++++++++++++++----------------
>  1 file changed, 266 insertions(+), 101 deletions(-)
> 
> diff --git a/src/shell.c b/src/shell.c
> index c5bb9c4..45e70f0 100644
> --- a/src/shell.c
> +++ b/src/shell.c
> @@ -36,6 +36,7 @@
>  #include "compositor.h"
>  #include "desktop-shell-server-protocol.h"
>  #include "workspaces-server-protocol.h"
> +#include "../shared/hash.h"
>  #include "../shared/config-parser.h"
>  
>  #define DEFAULT_NUM_WORKSPACES 1
> @@ -62,6 +63,8 @@ struct workspace_container {
>  	unsigned int current;
>  	unsigned int num;
>  
> +	struct weston_output *output;
> +
>  	struct weston_animation animation;
>  	struct wl_list anim_sticky_list;
>  	int anim_dir;
> @@ -120,7 +123,7 @@ struct desktop_shell {
>  	struct wl_listener lock_surface_listener;
>  
>  	struct {
> -		struct workspace_container container;
> +		struct hash_table *table;
>  		unsigned int default_num;
>  
>  		struct wl_list client_list;
> @@ -234,9 +237,6 @@ static void
>  activate(struct desktop_shell *shell, struct weston_surface *es,
>  	 struct weston_seat *seat);
>  
> -static struct workspace *
> -get_current_workspace(struct desktop_shell *shell);
> -
>  static struct shell_surface *
>  get_shell_surface(struct weston_surface *surface);
>  
> @@ -576,50 +576,98 @@ workspace_restack_surface(struct workspace *ws, struct shell_surface *shsurf)
>  }
>  
>  static struct workspace *
> -get_workspace(struct desktop_shell *shell, unsigned int index)
> +workspace_container_get(struct workspace_container *container,
> +			unsigned int index)
>  {
> -	struct workspace **pws = shell->workspaces.container.workspaces.data;
> -	assert(index < shell->workspaces.container.num);
> -	pws += index;
> -	return *pws;
> +	struct workspace **pws = container->workspaces.data;
> +	return *(pws + index);
>  }
>  
>  static struct workspace *
> -get_current_workspace(struct desktop_shell *shell)
> +workspace_container_get_current(struct workspace_container *container)
>  {
> -	return get_workspace(shell, shell->workspaces.container.current);
> +	return workspace_container_get(container, container->current);
>  }
>  
> -static void
> -activate_workspace(struct desktop_shell *shell, unsigned int index)
> +static struct workspace_container *
> +find_first_workspace_container(struct desktop_shell *shell)
>  {
> -	struct workspace *ws;
> +	struct weston_output *output;
> +	struct workspace_container *container;
>  
> -	ws = get_workspace(shell, index);
> -	wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
> +	output = container_of(shell->compositor->output_list.next,
> +			      struct weston_output, link);

I'd like to have an assert added with all code that assumes we have at
least one output. There will be a time when we want to be able to deal
with a temporary zero outputs cases, and having asserts around will make
finding all places that need fixing easier. Or something to the same
effect.

Hmm, or maybe just grepping for output_list with a container_of is
enough.

> +	container = hash_table_lookup(shell->workspaces.table, output->id);
> +
> +	return container;
> +}
> +
> +static struct workspace_container *
> +find_focused_workspace_container(struct desktop_shell *shell,
> +				 struct wl_seat *seat)
> +{
> +	int x, y;
> +	struct weston_output *output;
> +
> +	if (seat->pointer == NULL)
> +		return NULL;
> +
> +	x = wl_fixed_to_int(seat->pointer->x);
> +	y = wl_fixed_to_int(seat->pointer->y);
> +	wl_list_for_each(output, &shell->compositor->output_list, link)
> +		if (pixman_region32_contains_point(&output->region,
> +						   x, y, NULL))
> +			return hash_table_lookup(shell->workspaces.table,
> +						 output->id);
>  
> -	shell->workspaces.container.current = index;
> +	return NULL;
> +}
> +
> +static struct workspace_container *
> +get_workspace_container(struct desktop_shell *shell, uint32_t container_id)
> +{
> +	return hash_table_lookup(shell->workspaces.table, container_id);
> +}
> +
> +static struct workspace *
> +find_workspace_for(struct desktop_shell *shell, struct weston_surface *surface)
> +{
> +	struct workspace_container *container;
> +
> +	if (surface->output)
> +		container = get_workspace_container(shell, surface->output->id);
> +	else
> +		container = find_first_workspace_container(shell);
> +	return workspace_container_get_current(container);
>  }
>  
>  static void
> -workspace_container_release(struct workspace_container *container)
> +workspace_container_destroy(struct workspace_container *container)
>  {
>  	struct workspace **pws;
>  
>  	wl_array_for_each(pws, &container->workspaces)
>  		workspace_destroy(*pws);
>  	wl_array_release(&container->workspaces);
> +	free(container);
>  }
>  
> -static int
> -workspace_container_init(struct workspace_container *container,
> -			 struct desktop_shell *shell)
> +static struct workspace_container *
> +workspace_container_create(struct desktop_shell *shell,
> +			   struct weston_output *output,
> +			   unsigned int num)
>  {
> +	struct workspace_container *container;
>  	struct workspace **pws;
>  	unsigned int i;
>  
> +	container = malloc(sizeof *container);
> +	if (container == NULL)
> +		return NULL;
> +
> +	container->output = output;

I think we will be needing a destroy signal for outputs, and you could
hook into it here - do you want to dynamically remove the workspace
when the output goes away?

Yeah, we probably have bigger problems already with output
hot-unplugging, just an idea to keep in mind.

If you had a destroy signal in weston_output, could you not replace the
hash table lookups with a wl_signal_get()? Would that make anything
easier?


Thanks,
pq


More information about the wayland-devel mailing list