[PATCH] [RFC]Shell: Hide panels when compositor has a top fullscreen surface.

Kristian Høgsberg krh at bitplanet.net
Fri Feb 17 19:09:46 PST 2012


On Tue, Feb 14, 2012 at 3:18 AM,  <zhiwen.wu at intel.com> wrote:
> From: Alex Wu <zhiwen.wu at intel.com>
>
>  Hi krh

Hi Alex,

>  This patch is the implementation of the method 3 of the proposal(http://lists.freedesktop.org/archives/wayland-devel/2012-February/002085.html)
>  for handling panels when compositor has a top fullscreen regular surface, and rebases on commit
>  8fb8d3b1b5b4ef7836a61f111aeb4aaa87ae89e4. Need your suggestion and ideas.
>  The main logic and modifications are as follows:
>
>  1.Add a struct wl_list wl_shell::hidden_panels to store the hidden panels.

I think it's better to just raise the fullscreen surface above the
panels.  This is a little tricky right now because of the simplistic
surface_list, but I'll try to fix that soon.  I'm thinking we'll have
a new struct wl_layer, which will be a list of surfaces.  Then we'll
have fade_layer, pointer_layer, fullscreen_layer, panels_layer,
toplevel_layer and background_layer.  Then it will be just a matter of
pulling the surface out of toplevel_layer and putting it into
fullscreen_layer.

>  2.Add a hook weston_shell:prepare_repaint to do the stacking adjustment before output repainting.

Not sure about this part.  Within shell.c, we should be able to know
when we go from "fullscreen surface on top" to "something else on top"
and vice versa.  So lets handle the stack reordering there instead of
checking it on every repaint.

Kristian

>  3.In the hook, check if we had a top and fullscreen surface.
>   If yes, remove the panel surface from weston_compositor::surface_list and store them to wl_shell:hidden_panels.
>   If no, and we have hidden panels, unhide them.
>  4.For now, popup surface is treated as regular surface, when popup surface got on top of fullscreen surface,
>   panels will be unhidden.
>  PS: Just a RFC, coding style is not aligned.
> ---
>  src/compositor.c |    2 +
>  src/compositor.h |    1 +
>  src/shell.c      |  125 ++++++++++++++++++++++++++++++++++++++++++++++++------
>  3 files changed, 115 insertions(+), 13 deletions(-)
>
> diff --git a/src/compositor.c b/src/compositor.c
> index ab90ded..5ef830e 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -966,6 +966,8 @@ weston_output_repaint(struct weston_output *output, int msecs)
>                overlap, surface_overlap;
>        int32_t width, height;
>
> +  ec->shell->prepare_repaint (ec->shell, output);
> +
>        width = output->current->width +
>                output->border.left + output->border.right;
>        height = output->current->height +
> diff --git a/src/compositor.h b/src/compositor.h
> index 966d3f4..bc1f72b 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -135,6 +135,7 @@ struct weston_shell {
>                          struct weston_surface *surface,
>                          GLfloat x, GLfloat y, int32_t width, int32_t height);
>        void (*destroy)(struct weston_shell *shell);
> +       void (*prepare_repaint)(struct weston_shell *shell, struct weston_output *output);
>  };
>
>  enum {
> diff --git a/src/shell.c b/src/shell.c
> index 66c4f01..85a487f 100644
> --- a/src/shell.c
> +++ b/src/shell.c
> @@ -57,6 +57,7 @@ struct wl_shell {
>        struct shell_surface *lock_surface;
>        struct wl_listener lock_surface_listener;
>        struct wl_list hidden_surface_list;
> +       struct wl_list hidden_panels;
>
>        struct wl_list backgrounds;
>        struct wl_list panels;
> @@ -70,6 +71,7 @@ struct wl_shell {
>        } screensaver;
>  };
>
> +/*FIXME:Using bit flag for the type due to some surface may be both toplevel and fullscreen*/
>  enum shell_surface_type {
>        SHELL_SURFACE_NONE,
>
> @@ -600,7 +602,7 @@ get_shell_surface(struct weston_surface *surface)
>        struct wl_list *lst = &surface->surface.resource.destroy_listener_list;
>        struct wl_listener *listener;
>
> -       /* search the destroy listener list for our callback */
> +  /* search the destroy listener list for our callback */
>        wl_list_for_each(listener, lst, link) {
>                if (listener->func == shell_handle_surface_destroy) {
>                        return container_of(listener, struct shell_surface,
> @@ -1266,6 +1268,101 @@ center_on_output(struct weston_surface *surface, struct weston_output *output)
>        weston_surface_set_position(surface, output->x + x, output->y + y);
>  }
>
> +static struct weston_surface *
> +top_regular_surface (struct weston_shell *base)
> +{
> +       struct wl_shell *shell = container_of(base, struct wl_shell, shell);
> +       struct weston_compositor *compositor = shell->compositor;
> +       struct wl_list *list;
> +  struct weston_surface *surf;
> +       struct weston_surface *tmp;
> +  bool   done = false;
> +
> +  list = &compositor->surface_list;
> +
> +  wl_list_for_each_safe(surf, tmp, list, link) {
> +    /*skip non-client surface*/
> +               if (surf->surface.resource.client == NULL)
> +                       continue;
> +    if (get_shell_surface_type(surf) == SHELL_SURFACE_LOCK)
> +      continue;
> +    if (get_shell_surface_type(surf) == SHELL_SURFACE_SCREENSAVER)
> +      continue;
> +    if (get_shell_surface_type(surf) == SHELL_SURFACE_PANEL)
> +      continue;
> +    if (get_shell_surface_type(surf) == SHELL_SURFACE_BACKGROUND) {
> +      break;
> +    }
> +    /*got the top regular surface*/
> +    done = true;
> +    break;
> +  }
> +
> +  if (!done) {
> +    printf ("no regular surface\n");
> +    surf = NULL;
> +  }
> +
> +  return surf;
> +}
> +
> +static bool
> +is_fullscreen_surface (struct weston_surface *base)
> +{
> +  struct shell_surface *shsurf;
> +  enum shell_surface_type surf_type;
> +
> +  if (!base) {
> +    return false;
> +  }
> +
> +  shsurf = get_shell_surface (base);
> +  surf_type = get_shell_surface_type (base);
> +
> +  if (surf_type == SHELL_SURFACE_FULLSCREEN)
> +    return true;
> +  else
> +    return false;
> +}
> +
> +static void
> +prepare_repaint (struct weston_shell *base, struct weston_output *output)
> +{
> +  struct wl_shell *shell = container_of(base, struct wl_shell, shell);
> +       struct weston_compositor *compositor = shell->compositor;
> +  struct weston_surface *top_regular_surf;
> +       struct weston_surface *tmp;
> +  struct shell_surface *panel;
> +  bool   do_damage = false;
> +
> +  top_regular_surf = top_regular_surface (base);
> +
> +  if (is_fullscreen_surface (top_regular_surf)){
> +    if (wl_list_empty (&shell->hidden_panels) && !wl_list_empty (&shell->panels)) {
> +      /*hide panels*/
> +      wl_list_for_each(panel, &shell->panels, link) {
> +        panel->surface->output = NULL;
> +        wl_list_remove(&panel->surface->link);
> +        wl_list_insert(shell->hidden_panels.prev, &panel->surface->link);
> +      }
> +      do_damage = true;
> +    }
> +  } else {
> +    if (!wl_list_empty (&shell->hidden_panels)) {
> +      /*unhide panels*/
> +      struct wl_list *list = weston_compositor_top(compositor);
> +      wl_list_insert_list(list, &shell->hidden_panels);
> +      wl_list_init(&shell->hidden_panels);
> +      do_damage = true;
> +    }
> +  }
> +
> +  if (do_damage) {
> +    weston_output_damage (output);
> +  }
> +  return;
> +}
> +
>  static void
>  map(struct weston_shell *base,
>     struct weston_surface *surface, int32_t width, int32_t height)
> @@ -1344,14 +1441,14 @@ map(struct weston_shell *base,
>                break;
>        default:
>                /* everything else just below the panel */
> -               if (!wl_list_empty(&shell->panels)) {
> -                       struct shell_surface *panel =
> -                               container_of(shell->panels.prev,
> -                                            struct shell_surface, link);
> -                       wl_list_insert(&panel->surface->link, &surface->link);
> -               } else {
> -                       wl_list_insert(list, &surface->link);
> -               }
> +    if (!wl_list_empty(&shell->panels) && wl_list_empty (&shell->hidden_panels)) {
> +      struct shell_surface *panel =
> +        container_of(shell->panels.prev,
> +            struct shell_surface, link);
> +      wl_list_insert(&panel->surface->link, &surface->link);
> +    } else {
> +      wl_list_insert(list, &surface->link);
> +    }
>        }
>
>        if (do_configure) {
> @@ -1399,10 +1496,10 @@ configure(struct weston_shell *base, struct weston_surface *surface,
>                do_configure = !do_configure;
>                /* fall through */
>        case SHELL_SURFACE_FULLSCREEN:
> -               center_on_output(surface, surface->fullscreen_output);
> -               break;
> -       default:
> -               break;
> +    center_on_output(surface, surface->fullscreen_output);
> +    break;
> +  default:
> +    break;
>        }
>
>        /*  XXX: would a fullscreen surface need the same handling? */
> @@ -1589,8 +1686,10 @@ shell_init(struct weston_compositor *ec)
>        shell->shell.map = map;
>        shell->shell.configure = configure;
>        shell->shell.destroy = shell_destroy;
> +       shell->shell.prepare_repaint = prepare_repaint;
>
>        wl_list_init(&shell->hidden_surface_list);
> +       wl_list_init(&shell->hidden_panels);
>        wl_list_init(&shell->backgrounds);
>        wl_list_init(&shell->panels);
>        wl_list_init(&shell->screensaver.surfaces);
> --
> 1.7.5.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list