/* Data structures per surface type */
shell_surface_type_t type;
+ struct
+ {
+ int32_t x, y;
+ uint32_t flags;
+ pepper_seat_t *seat;
+ } popup;
+
/* (*map) */
void (*shell_surface_map)(shell_surface_t *shsurf);
pepper_bool_t mapped;
void
shell_surface_set_toplevel(shell_surface_t *shsurf);
+void
+shell_surface_set_popup(shell_surface_t *shsurf, pepper_seat_t *seat, pepper_surface_t *parent,
+ int32_t x, int32_t y, uint32_t flags);
+
pepper_bool_t
init_wl_shell(desktop_shell_t *shell);
shsurf->mapped = PEPPER_FALSE;
}
+void
+shell_surface_set_popup(shell_surface_t *shsurf,
+ pepper_seat_t *seat,
+ pepper_surface_t *parent,
+ int32_t x,
+ int32_t y,
+ uint32_t flags)
+{
+ shell_surface_set_parent(shsurf, parent);
+
+ shsurf->popup.x = x;
+ shsurf->popup.y = y;
+ shsurf->popup.flags = flags;
+ shsurf->popup.seat = seat;
+
+ shell_surface_set_type(shsurf, SHELL_SURFACE_TYPE_POPUP);
+}
+
static void
shell_surface_set_position(shell_surface_t *shsurf, int32_t x, int32_t y)
{
shsurf->mapped = PEPPER_TRUE;
}
+static void
+shell_surface_map_popup(shell_surface_t *shsurf)
+{
+ shell_surface_t *parent = get_shsurf_from_surface(shsurf->parent, shsurf->shell);
+
+ /* Set position as relatively */
+ pepper_view_set_parent(shsurf->view, parent->view);
+ shell_surface_set_position(shsurf, shsurf->popup.x, shsurf->popup.y);
+
+ pepper_view_map(shsurf->view);
+
+ /* TODO: add_popup_grab(), but how? */
+}
+
void
shell_surface_set_type(shell_surface_t *shsurf, shell_surface_type_t type)
{
case SHELL_SURFACE_TYPE_TOPLEVEL:
shsurf->shell_surface_map = shell_surface_map_toplevel;
break;
+ case SHELL_SURFACE_TYPE_POPUP:
+ shsurf->shell_surface_map = shell_surface_map_popup;
+ break;
default :
/* XXX: Maybe some logs be needed */
break;
}
static void
-wl_shell_surface_set_popup(struct wl_client *client, struct wl_resource *resource,
- struct wl_resource *seat, uint32_t serial, struct wl_resource *parent,
- int32_t x, int32_t y, uint32_t flags)
-{
- /* TODO */
+wl_shell_surface_set_popup(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *seat_res,
+ uint32_t serial,
+ struct wl_resource *parent_res,
+ int32_t x,
+ int32_t y,
+ uint32_t flags)
+{
+ shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+ pepper_seat_t *seat;
+ pepper_surface_t *parent;
+
+ if (!seat_res)
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Invalid seat");
+ return ;
+ }
+ seat = wl_resource_get_user_data(seat_res);
+
+ if (!parent_res)
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Invalid parent surface");
+ return ;
+ }
+ parent = wl_resource_get_user_data(parent_res);
+
+ shell_surface_set_popup(shsurf, seat, parent, x, y, flags);
}
static void
int32_t x,
int32_t y)
{
- shell_client_t *shell_client = wl_resource_get_user_data(resource);
- pepper_surface_t *surface = wl_resource_get_user_data(surface_resource);
- shell_surface_t *shsurf;
+ shell_client_t *shell_client = wl_resource_get_user_data(resource);
+ pepper_surface_t *surface;
+ pepper_seat_t *seat;
+ pepper_surface_t *parent;
+ shell_surface_t *shsurf;
+
+ /* Check parameters */
+ if (!surface_resource)
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "Invalid surface");
+ return ;
+ }
+ surface = wl_resource_get_user_data(surface_resource);
+ if (!seat_resource)
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "Invalid seat");
+ return ;
+ }
+ seat = wl_resource_get_user_data(seat_resource);
+
+ if (!parent_resource)
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "Invalid parent surface");
+ return ;
+ }
+ parent = wl_resource_get_user_data(parent_resource);
+
+ /**
+ * TODO: check parent state
+ * 1. Parent must have either a xdg_surface or xdg_popup role
+ * 2. If there is an existing popup when creating a new popup, the
+ * parent must be the current topmost popup.
+ */
+ {
+ const char *role = pepper_surface_get_role(parent);
+
+ if (strcmp(role, "xdg_surface") && strcmp(role, "xdg_popup"))
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Invalid xdg_popup parent");
+ return ;
+ }
+ }
+
+ /* Set role */
if (!pepper_surface_set_role(surface, "xdg_popup"))
{
wl_resource_post_error(resource, XDG_SHELL_ERROR_ROLE,
&xdg_popup_implementation, 1, id);
if (!shsurf)
wl_client_post_no_memory(client);
+
+ shell_surface_set_popup(shsurf, seat, parent, x, y, 0);
}
static void