On Tue, Aug 21, 2012 at 1:49 PM, <tecto...@gmail.com> wrote: > From: Ning Tang <ning.t...@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 <tecto...@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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/wayland-devel _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel