[PATCH 09/14] tablet-shell: add shell_surface in tablet-shell.

Philipp Brüschweiler blei42 at gmail.com
Tue Aug 21 08:32:57 PDT 2012


On Tue, Aug 21, 2012 at 1:49 PM,  <tecton69 at gmail.com> wrote:
> From: Ning Tang <ning.tang at intel.com>
>
> Since now toytoolkit and simple programs use shell_surface to show on
> screen, we add it in tablet-shell to let them show.
> But we only need serveral feature in tablet shell, the wl_shell is too
> big and not suitable for tablet-shell.
>
> And it is helpful to fill in the interface of wl_shell for now. Then we
> could make toytoolkit, efl applications run against tablet-shell.
> And this won't influence our work to differenciate tablet-shell to
> dekstop-shell. Once wl_shell was modified in wayland protocol, we will
> change this part too. We will add tablet_shell interface when it is necessary.
>
> Now once a shell_surface is requested, it will be centered on screen and
> have a black background surface.
> We reserve the set_fullscreen method and all other implementation is
> just return.
>
>  Signed-off-by: Ning Tang <tecton69 at gmail.com>
>
> ---
>  src/tablet-shell.c | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 379 insertions(+)
>
> diff --git a/src/tablet-shell.c b/src/tablet-shell.c
> index 4a77681..89f84bf 100644
> --- a/src/tablet-shell.c
> +++ b/src/tablet-shell.c
> @@ -75,6 +75,28 @@ struct tablet_shell {
>         struct wl_event_source *long_press_source;
>  };
>
> +struct shell_surface {
> +       struct wl_resource resource;
> +
> +       struct weston_surface *surface;
> +       struct weston_surface *parent_surface;
> +       struct weston_surface *black_surface;
> +       struct wl_listener surface_destroy_listener;
> +       struct tablet_shell *shell;
> +
> +       struct weston_output *output;
> +       struct wl_list link;
> +
> +       int is_fullscreen;
> +       struct {
> +               enum wl_shell_surface_fullscreen_method type;
> +               struct weston_transform transform;
> +               uint32_t framerate;
> +       } fullscreen;
> +
> +       const struct weston_shell_client *client;
> +};
> +
>  struct tablet_client {
>         struct wl_resource resource;
>         struct tablet_shell *shell;
> @@ -84,6 +106,273 @@ struct tablet_client {
>  };
>
>  static void
> +shell_surface_configure(struct weston_surface *surface,
> +                       int32_t sx, int32_t sy);
> +
> +static void
> +black_surface_configure(struct weston_surface *es,
> +                       int32_t sx, int32_t sy);
> +
> +static struct shell_surface *
> +get_shell_surface(struct weston_surface *surface)
> +{
> +       if (surface->configure == shell_surface_configure)
> +               return surface->private;
> +       else if (surface->configure == black_surface_configure)
> +               return get_shell_surface(surface->private);
> +       else
> +               return NULL;
> +}
> +
> +static void
> +destroy_shell_surface(struct shell_surface *shsurf)
> +{
> +       wl_list_remove(&shsurf->surface_destroy_listener.link);
> +       shsurf->surface->configure = NULL;
> +
> +       if (shsurf->black_surface)
> +       {
> +               wl_list_remove(&shsurf->black_surface->layer_link);
> +               weston_surface_destroy(shsurf->black_surface);
> +       }
> +       wl_list_remove(&shsurf->link);
> +       free(shsurf);
> +       weston_surface_damage(shsurf->shell->home_surface);

It is undefined behaviour to access a pointer once its data has been
free()'d (IIRC?).

> +}
> +
> +static void
> +shell_destroy_shell_surface(struct wl_resource *resource)
> +{
> +       struct shell_surface *shsurf = resource->data;
> +       destroy_shell_surface(shsurf);
> +}
> +
> +static void
> +shell_handle_surface_destroy(struct wl_listener *listener, void *data)
> +{
> +       struct shell_surface *shsurf =
> +               container_of(listener, struct shell_surface,
> +                            surface_destroy_listener);
> +       if (shsurf->resource.client) {
> +               wl_resource_destroy(&shsurf->resource);
> +       } else {
> +               wl_signal_emit(&shsurf->resource.destroy_signal,
> +                              &shsurf->resource);
> +               destroy_shell_surface(shsurf);
> +       }
> +}
> +static void
> +shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
> +               uint32_t serial)
> +{
> +       return;
> +}
> +
> +static void
> +shell_surface_set_title(struct wl_client *client,
> +                       struct wl_resource *resource, const char *title)
> +{
> +       return;
> +}
> +
> +static void
> +shell_surface_set_class(struct wl_client *client,
> +                       struct wl_resource *resource, const char *class)
> +{
> +       return;
> +}
> +
> +static void
> +shell_surface_move(struct wl_client *client, struct wl_resource *resource,
> +                       struct wl_resource *seat_resource, uint32_t serial)
> +{
> +       return;
> +}
> +
> +static void
> +shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
> +                       struct wl_resource *seat_resource, uint32_t serial,
> +                       uint32_t edges)
> +{
> +       return;
> +}
> +
> +static void
> +shell_surface_set_toplevel(struct wl_client *client,
> +                       struct wl_resource *resource)
> +{
> +       return;
> +}
> +
> +static void
> +shell_surface_set_transient(struct wl_client *client,
> +                       struct wl_resource *resource,
> +                       struct wl_resource *parent_resource,
> +                       int x, int y, uint32_t flags)
> +{
> +       struct shell_surface *shsurf = resource->data;
> +       if (shsurf->resource.client) {
> +               wl_resource_destroy(&shsurf->resource);
> +       } else {
> +               wl_signal_emit(&shsurf->resource.destroy_signal,
> +                              &shsurf->resource);
> +               destroy_shell_surface(shsurf);
> +       }
> +}
> +
> +static void
> +shell_surface_set_fullscreen(struct wl_client *client,
> +                       struct wl_resource *resource,
> +                       uint32_t method,
> +                       uint32_t framerate,
> +                       struct wl_resource *output_resource)
> +{
> +       struct shell_surface *shsurf = resource->data;
> +       struct weston_surface *es = shsurf->surface;
> +
> +       if (output_resource)
> +               shsurf->output = output_resource->data;
> +       else
> +               shsurf->output = container_of(es->compositor->output_list.next,
> +                           struct weston_output, link);
> +
> +       shsurf->client->send_configure(shsurf->surface, 0,
> +                                      shsurf->output->current->width,
> +                                      shsurf->output->current->height);
> +}
> +
> +static void
> +shell_surface_set_popup(struct wl_client *client,
> +                       struct wl_resource *resource,
> +                       struct wl_resource *seat_resource,
> +                       uint32_t serial,
> +                       struct wl_resource *parent_resource,
> +                       int32_t x, int32_t y, uint32_t flags)
> +{
> +       return;
> +}
> +
> +static void
> +shell_surface_set_maximized(struct wl_client *client,
> +                       struct wl_resource *resource,
> +                       struct wl_resource *output_resource)
> +{
> +       return;
> +}
> +
> +static const struct wl_shell_surface_interface shell_surface_implementation = {
> +       shell_surface_pong,
> +       shell_surface_move,
> +       shell_surface_resize,
> +       shell_surface_set_toplevel,
> +       shell_surface_set_transient,
> +       shell_surface_set_fullscreen,
> +       shell_surface_set_popup,
> +       shell_surface_set_maximized,
> +       shell_surface_set_title,
> +       shell_surface_set_class
> +};
> +
> +static struct shell_surface *
> +create_shell_surface(void *shell, struct weston_surface *surface,
> +                       const struct weston_shell_client *client)
> +{
> +       struct shell_surface *shsurf;
> +
> +       if (surface->configure) {
> +               weston_log("surface->configure already set\n");
> +               return NULL;
> +       }
> +
> +       shsurf = calloc(1, sizeof *shsurf);
> +               if (!shsurf) {
> +               weston_log("no memory to allocate shell surface\n");
> +               return NULL;
> +       }
> +
> +       surface->configure = shell_surface_configure;
> +       surface->private = shsurf;
> +       surface->compositor->shell_interface.shell = shell;
> +
> +       shsurf->shell = (struct tablet_shell *) shell;
> +       shsurf->surface = surface;
> +
> +       wl_signal_init(&shsurf->resource.destroy_signal);
> +       shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
> +       wl_signal_add(&surface->surface.resource.destroy_signal,
> +                     &shsurf->surface_destroy_listener);
> +
> +       /* init link so its safe to always remove it in destroy_shell_surface */
> +       wl_list_init(&shsurf->link);
> +
> +       shsurf->client = client;
> +
> +       return shsurf;
> +}
> +
> +static void
> +send_configure(struct weston_surface *surface,
> +              uint32_t edges, int32_t width, int32_t height)
> +{
> +       struct shell_surface *shsurf = get_shell_surface(surface);
> +
> +       wl_shell_surface_send_configure(&shsurf->resource,
> +                                       edges, width, height);
> +}
> +
> +static const struct weston_shell_client shell_client = {
> +       send_configure
> +};
> +
> +static void
> +shell_get_shell_surface(struct wl_client *client,
> +                       struct wl_resource *resource,
> +                       uint32_t id,
> +                       struct wl_resource *surface_resource)
> +{
> +       struct weston_surface *surface = surface_resource->data;
> +       struct tablet_shell *shell = resource->data;
> +       struct shell_surface *shsurf;
> +
> +       if (get_shell_surface(surface)) {
> +               wl_resource_post_error(surface_resource,
> +                                      WL_DISPLAY_ERROR_INVALID_OBJECT,
> +                                      "tablet_shell::get_shell_surface already requested");
> +               return;
> +       }
> +
> +       shsurf = create_shell_surface(shell, surface, &shell_client);
> +       if (!shsurf) {
> +               wl_resource_post_error(surface_resource,
> +                                      WL_DISPLAY_ERROR_INVALID_OBJECT,
> +                                      "surface->configure already set");
> +               return;
> +       }
> +
> +       shsurf->resource.destroy = shell_destroy_shell_surface;
> +       shsurf->resource.object.id = id;
> +       shsurf->resource.object.interface = &wl_shell_surface_interface;
> +       shsurf->resource.object.implementation =
> +               (void (**)(void)) &shell_surface_implementation;
> +       shsurf->resource.data = shsurf;
> +
> +       wl_client_add_resource(client, &shsurf->resource);
> +}
> +
> +static const struct wl_shell_interface shell_implementation = {
> +       shell_get_shell_surface
> +};
> +
> +static void
> +bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
> +{
> +       struct tablet_shell *shell = data;
> +
> +       wl_client_add_object(client, &wl_shell_interface,
> +                            &shell_implementation, id, shell);
> +}
> +
> +static void
>  tablet_shell_destroy(struct wl_listener *listener, void *data);
>
>  static struct tablet_shell *
> @@ -193,6 +482,92 @@ tablet_shell_set_lockscreen(struct wl_client *client,
>  }
>
>  static void
> +center_on_output(struct weston_surface *surface, struct weston_output *output)
> +{
> +       struct weston_mode *mode = output->current;
> +       GLfloat x = (mode->width - surface->buffer->width) / 2;
> +       GLfloat y = (mode->height - surface->buffer->height) / 2;
> +
> +       weston_surface_configure(surface, output->x + x, output->y + y,
> +                                surface->buffer->width,
> +                                surface->buffer->height);
> +}
> +
> +static void
> +black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
> +{
> +       return;
> +}
> +
> +static struct weston_surface *
> +create_black_surface(struct weston_compositor *ec,
> +                    struct weston_surface *fs_surface,
> +                    GLfloat x, GLfloat y, int w, int h)
> +{
> +       struct weston_surface *surface = NULL;
> +
> +       surface = weston_surface_create(ec);
> +       if (surface == NULL) {
> +               weston_log("no memory\n");
> +               return NULL;
> +       }
> +
> +       surface->configure = black_surface_configure;
> +       surface->private = fs_surface;
> +       weston_surface_configure(surface, x, y, w, h);
> +       weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
> +       return surface;
> +}
> +
> +static void
> +shell_stack_fullscreen(struct shell_surface *shsurf)
> +{
> +       struct weston_surface *surface = shsurf->surface;
> +       struct weston_output *output = surface->output;
> +       struct tablet_shell *shell = shsurf->shell;
> +
> +       wl_list_remove(&surface->layer_link);
> +       wl_list_insert(&shell->application_layer.surface_list,
> +                      &surface->layer_link);
> +       weston_surface_damage(surface);
> +
> +       if (!shsurf->black_surface)
> +               shsurf->black_surface =
> +                       create_black_surface(surface->compositor,
> +                                            surface,
> +                                            output->x, output->y,
> +                                            output->current->width,
> +                                            output->current->height);
> +
> +       wl_list_remove(&shsurf->black_surface->layer_link);
> +       wl_list_insert(&surface->layer_link,
> +                      &shsurf->black_surface->layer_link);
> +       weston_surface_damage(shsurf->black_surface);
> +}
> +
> +static void
> +shell_surface_configure(struct weston_surface *surface,
> +                       int32_t sx, int32_t sy)
> +{
> +       struct tablet_shell *shell = get_shell(surface->compositor);
> +       struct shell_surface *shsurf = get_shell_surface(surface);
> +       struct weston_seat *seat;
> +
> +       if (!weston_surface_is_mapped(surface)) {
> +               tablet_shell_set_state(shell, STATE_TASK);
> +
> +               wl_list_insert(&shell->application_layer.surface_list,
> +                              &surface->layer_link);
> +               weston_surface_assign_output(surface);
> +               center_on_output(surface, surface->output);
> +               shell_stack_fullscreen(shsurf);
> +               wl_list_for_each(seat, &surface->compositor->seat_list, link)
> +                       weston_surface_activate(surface, seat);
> +               weston_compositor_schedule_repaint(shell->compositor);
> +       }
> +}
> +
> +static void
>  handle_switcher_surface_destroy(struct wl_listener *listener, void *data)
>  {
>         struct tablet_shell *shell =
> @@ -557,6 +932,10 @@ shell_init(struct weston_compositor *compositor)
>         wl_display_add_global(compositor->wl_display, &tablet_shell_interface,
>                               shell, bind_tablet_shell);
>
> +       if (wl_display_add_global(compositor->wl_display, &wl_shell_interface,
> +                                 shell, bind_shell) == NULL)
> +               return;
> +
>         loop = wl_display_get_event_loop(compositor->wl_display);
>         shell->long_press_source =
>                 wl_event_loop_add_timer(loop, long_press_handler, shell);
> --
> 1.7.11.5
>
> _______________________________________________
> 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