[PATCH 10/19] tablet-shell: add shell_surface in tablet-shell.
ning.tang at intel.com
ning.tang at intel.com
Mon Sep 24 19:39:55 PDT 2012
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 <ning.tang at intel.com>
---
src/tablet-shell.c | 378 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 378 insertions(+)
diff --git a/src/tablet-shell.c b/src/tablet-shell.c
index f10f11a..172ec79 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,272 @@ 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);
+}
+
+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 +481,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 =
@@ -554,6 +928,10 @@ module_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.12.1
More information about the wayland-devel
mailing list