{
pepper_object_t *compositor;
struct wl_resource *resource;
+ struct wl_list shell_surface_list;
+};
+
+enum shell_surface_type
+{
+ SHELL_SURFACE_TYPE_NONE,
+ SHELL_SURFACE_TYPE_TOPLEVEL,
+ SHELL_SURFACE_TYPE_FULLSCREEN,
+ SHELL_SURFACE_TYPE_POPUP,
+ SHELL_SURFACE_TYPE_MAXIMIZED
};
struct shell_surface
struct wl_client *client;
struct wl_resource *resource;
- struct wl_listener client_destroy_listener;
- struct wl_listener surface_destroy_listener;
+ pepper_object_t *parent;
+ struct wl_list child_list; /* children surfaces of this */
+ struct wl_list parent_link;
+
+ pepper_object_t *view;
+
+ enum shell_surface_type type;
+
+ char *title, *class_;
+
+ struct
+ {
+ int32_t x, y, width, height;
+ } geometry, saved;
struct wl_event_source *ping_timer;
pepper_bool_t need_pong;
+
+ struct wl_listener client_destroy_listener;
+ struct wl_listener surface_destroy_listener;
+
+ struct wl_list link; /* link */
};
shell_t *
shell_surface_t *
shell_surface_create(shell_t *shell, pepper_object_t *surface, struct wl_client *client,
- const char *role_name, const struct wl_interface *interface,
+ const struct wl_interface *interface,
const void *implemenetation, uint32_t version, uint32_t id);
void
shell_surface_ping(shell_surface_t *shsurf);
+void
+shell_surface_set_type(shell_surface_t *shsurf, enum shell_surface_type type);
+
+void
+shell_surface_set_parent(shell_surface_t *shsurf, pepper_object_t *parent_surface);
+
+/* */
+shell_surface_t *
+get_shsurf_from_surface(pepper_object_t *surface, shell_t *shell);
+
+void
+set_shsurf_to_surface(pepper_object_t *surface, shell_surface_t *shsurf);
+
pepper_bool_t
init_wl_shell(pepper_object_t *compositor);
shell_surface_t *shsurf =
pepper_container_of(listener, shell_surface_t, client_destroy_listener);
- wl_list_remove(&shsurf->client_destroy_listener.link);
+ if (!wl_list_empty(&shsurf->client_destroy_listener.link))
+ wl_list_remove(&shsurf->client_destroy_listener.link);
wl_list_init(&shsurf->client_destroy_listener.link);
remove_ping_timer(shsurf);
+
+ /* client_destroy -> client's surface destroy -> handle_surface_destroy */
}
static void
handle_surface_destroy(struct wl_listener *listener, void *data)
{
+ shell_surface_t *child, *tmp;
shell_surface_t *shsurf =
pepper_container_of(listener, shell_surface_t, surface_destroy_listener);
wl_list_remove(&shsurf->surface_destroy_listener.link);
+ /* We don't need to destroy pepper_view_t */
+
if (shsurf->resource)
wl_resource_destroy(shsurf->resource);
+ if (shsurf->title)
+ free(shsurf->title);
+
+ if (shsurf->class_)
+ free(shsurf->class_);
+
remove_ping_timer(shsurf);
+
+ wl_list_remove(&shsurf->parent_link);
+
+ wl_list_for_each_safe(child, tmp, &shsurf->child_list, parent_link)
+ shell_surface_set_parent(child, NULL);
+
+ wl_list_remove(&shsurf->link);
free(shsurf);
}
handle_resource_destroy(struct wl_resource *resource)
{
shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
shsurf->resource = NULL;
}
shell_surface_t *
shell_surface_create(shell_t *shell, pepper_object_t *surface, struct wl_client *client,
- const char *role_name, const struct wl_interface *interface,
+ const struct wl_interface *interface,
const void *implementation, uint32_t version, uint32_t id)
{
- shell_surface_t *shsurf;
-
- if (pepper_surface_get_role(surface))
- return NULL;
+ shell_surface_t *shsurf = NULL;
shsurf = calloc(1, sizeof(shell_surface_t));
if (!shsurf)
- return NULL;
+ {
+ PEPPER_ERROR("Memory allocation faiiled\n");
+ goto error;
+ }
shsurf->resource = wl_resource_create(client, interface, version, id);
if (!shsurf->resource)
{
- free(shsurf);
- return NULL;
+ PEPPER_ERROR("wl_resource_create failed\n");
+ goto error;
}
- shsurf->shell = shell;
+ shsurf->shell = shell;
shsurf->client = client;
+ shsurf->view = pepper_compositor_add_view(shell->compositor, NULL, NULL, surface);
+ if (!shsurf->view)
+ {
+ PEPPER_ERROR("pepper_compositor_add_view failed\n");
+ goto error;
+ }
+
+ /* TODO: Need to know about output size */
+ shsurf->geometry.x = rand()%10;
+ shsurf->geometry.y = rand()%10;
+ pepper_view_set_position(shsurf->view, shsurf->geometry.x, shsurf->geometry.y);
+
+ wl_list_init(&shsurf->link);
+ wl_list_insert(&shell->shell_surface_list, &shsurf->link);
+
+ wl_list_init(&shsurf->child_list);
+ wl_list_init(&shsurf->parent_link);
+
+ /* Set shell_surface_t to pepper_surface_t */
+ set_shsurf_to_surface(surface, shsurf);
+
wl_resource_set_implementation(shsurf->resource, implementation, shsurf, handle_resource_destroy);
shsurf->client_destroy_listener.notify = handle_client_destroy;
pepper_object_add_destroy_listener(surface, &shsurf->surface_destroy_listener);
return shsurf;
+
+error:
+ if (shsurf)
+ free(shsurf);
+
+ wl_client_post_no_memory(client);
+ return NULL;
}
static int
/* TODO: Do protocol specific ping. */
}
+
+void
+shell_surface_set_type(shell_surface_t *shsurf, enum shell_surface_type type)
+{
+ shsurf->type = type;
+}
+
+shell_surface_t *
+get_shsurf_from_surface(pepper_object_t *surface, shell_t *shell)
+{
+ return pepper_object_get_user_data(surface, shell);
+}
+
+void
+set_shsurf_to_surface(pepper_object_t *surface, shell_surface_t *shsurf)
+{
+ pepper_object_set_user_data(surface, shsurf->shell, shsurf, NULL);
+}
+
+void
+shell_surface_set_parent(shell_surface_t *shsurf, pepper_object_t *parent)
+{
+ shell_surface_t *parent_shsurf;
+
+ wl_list_remove(&shsurf->parent_link);
+ wl_list_init(&shsurf->parent_link);
+
+ shsurf->parent = parent;
+
+ if (parent)
+ {
+ parent_shsurf = get_shsurf_from_surface(parent, shsurf->shell);
+ if (parent_shsurf)
+ wl_list_insert(&parent_shsurf->child_list, &shsurf->parent_link);
+ }
+}
static void
shell_surface_set_toplevel(struct wl_client *client, struct wl_resource *resource)
{
- /* TODO */
+ shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+ shell_surface_set_parent(shsurf, NULL);
+
+ shell_surface_set_type(shsurf, SHELL_SURFACE_TYPE_TOPLEVEL);
+
+ pepper_view_set_visibility(shsurf->view, PEPPER_TRUE);
}
static void
static void
shell_surface_set_maximized(struct wl_client *client, struct wl_resource *resource,
- struct wl_resource *output)
+ struct wl_resource *output_res)
{
/* TODO */
}
shell_surface_set_title(struct wl_client *client, struct wl_resource *resource,
const char *title)
{
- /* TODO */
+ shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+ if (shsurf->title)
+ free(shsurf->title);
+
+ shsurf->title = strdup(title);
+
+ if (!shsurf->title)
+ wl_client_post_no_memory(client);
}
static void
shell_surface_set_class(struct wl_client *client, struct wl_resource *resource,
const char *class_)
{
- /* TODO */
+ shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+ if (shsurf->class_)
+ free(shsurf->class_);
+
+ shsurf->class_ = strdup(class_);
+
+ if (!shsurf->class_)
+ wl_client_post_no_memory(client);
}
static const struct wl_shell_surface_interface shell_surface_implementation =
uint32_t id, struct wl_resource *surface_resource)
{
pepper_object_t *surface = wl_resource_get_user_data(surface_resource);
- shell_t *shell = wl_resource_get_user_data(resource);
+ shell_t *shell = wl_resource_get_user_data(resource);
+
+ if (!pepper_surface_set_role(surface, "wl_shell_surface"))
+ {
+ wl_resource_post_error(resource, WL_SHELL_ERROR_ROLE,
+ "Assign \"wl_shell_surface\" to wl_surface failed\n");
+ return ;
+ }
- shell_surface_create(shell, surface, client, "wl_shell_surface", &wl_shell_surface_interface,
+ shell_surface_create(shell, surface, client, &wl_shell_surface_interface,
&shell_surface_implementation, 1, id);
}