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

Tang, Ning ning.tang at intel.com
Tue Aug 21 19:57:20 PDT 2012



> -----Original Message-----
> From: Philipp Brüschweiler [mailto:blei42 at gmail.com]
> Sent: Tuesday, August 21, 2012 11:33 PM
> To: tecton69 at gmail.com
> Cc: wayland-devel at lists.freedesktop.org; juan.j.zhao at linux.intel.com; Tang,
> Ning
> Subject: Re: [PATCH 09/14] tablet-shell: add shell_surface in tablet-shell.
> 
> 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?).
> 
It was my mistake...that line should be removed because at first it has only one
surface and after it's destroyed, it will show the homescreen. But later have
multiple surfaces.

Thank you.

> > +}
> > +
> > +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