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