From: Seunghun Lee Date: Wed, 23 Aug 2023 02:09:12 +0000 (+0900) Subject: xdg_shell_v6: Add zxdg_popup_v6 implementation X-Git-Tag: accepted/tizen/unified/20230828.145929^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8af00baa1b340ab629e6374254ab058e5a23e7c7;p=platform%2Fcore%2Fuifw%2Flibds.git xdg_shell_v6: Add zxdg_popup_v6 implementation Change-Id: Ia5594fc42744b3d707837140bd82b2ee346f3d6d --- diff --git a/include/libds/types/ds_xdg_shell_v6.h b/include/libds/types/ds_xdg_shell_v6.h index fc34553..b846c0c 100644 --- a/include/libds/types/ds_xdg_shell_v6.h +++ b/include/libds/types/ds_xdg_shell_v6.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include enum ds_xdg_surface_v6_role @@ -96,9 +98,19 @@ struct ds_xdg_toplevel_v6 bool sent_initial_configure; }; -struct ds_xdg_popup +struct ds_xdg_popup_v6 { + struct wl_resource *resource; + struct ds_xdg_surface_v6 *base; + + struct ds_surface *parent; + struct ds_seat *seat; + + struct ds_box geometry; + + struct wl_list link; // ds_xdg_surface_v6::popups + bool committed; }; struct ds_xdg_surface_v6_state @@ -119,7 +131,7 @@ struct ds_xdg_surface_v6 union { struct ds_xdg_toplevel_v6 *toplevel; - struct ds_xdg_popup *popup; + struct ds_xdg_popup_v6 *popup; }; struct wl_resource *resource; @@ -127,6 +139,7 @@ struct ds_xdg_surface_v6 struct wl_event_source *configure_idle; uint32_t scheduled_serial; struct wl_list configure_list; + struct wl_list popups; // ds_xdg_popup_v6.link struct ds_xdg_surface_v6_state current, pending; diff --git a/src/xdg_shell_v6/meson.build b/src/xdg_shell_v6/meson.build index 1370be4..bfac814 100644 --- a/src/xdg_shell_v6/meson.build +++ b/src/xdg_shell_v6/meson.build @@ -2,6 +2,7 @@ libds_xdg_shell_v6_files = [ 'xdg_shell_v6.c', 'xdg_surface_v6.c', 'xdg_toplevel_v6.c', + 'xdg_popup_v6.c', 'xdg_positioner_v6.c', ] diff --git a/src/xdg_shell_v6/xdg_popup_v6.c b/src/xdg_shell_v6/xdg_popup_v6.c new file mode 100644 index 0000000..2444fd0 --- /dev/null +++ b/src/xdg_shell_v6/xdg_popup_v6.c @@ -0,0 +1,144 @@ +#include + +#include "libds/log.h" +#include "libds/util/box.h" +#include "xdg_shell_v6.h" + +static void +xdg_popup_v6_handle_resource_destroy(struct wl_resource *resource) +{ + struct ds_xdg_popup_v6 *popup; + + popup = wl_resource_get_user_data(resource); + if (!popup) + return; + + zxdg_popup_v6_send_popup_done(popup->resource); + destroy_xdg_surface_v6_role(popup->base); +} + +static void +xdg_popup_v6_handle_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +xdg_popup_v6_handle_grab(struct wl_client *wl_client, + struct wl_resource *resource, struct wl_resource *seat_resource, + uint32_t serial) +{ + struct ds_xdg_popup_v6 *popup; + + popup = wl_resource_get_user_data(resource); + if (!popup) + return; + + if (popup->committed) { + wl_resource_post_error(popup->resource, + ZXDG_POPUP_V6_ERROR_INVALID_GRAB, + "xdg_popup already is mapped"); + return; + } + + // TODO handle grab +} + +static const struct zxdg_popup_v6_interface xdg_popup_v6_impl = { + .destroy = xdg_popup_v6_handle_destroy, + .grab = xdg_popup_v6_handle_grab, +}; + +const struct ds_surface_role xdg_popup_v6_surface_role = { + .name = "xdg_popup_v6", +}; + +struct ds_xdg_popup_v6 * +create_xdg_popup_v6(struct ds_xdg_surface_v6 *surface, + struct ds_xdg_surface_v6 *parent, + struct ds_xdg_positioner_v6 *positioner, uint32_t id) +{ + struct ds_xdg_popup_v6 *popup; + + if (!ds_surface_set_role(surface->ds_surface, &xdg_popup_v6_surface_role, + NULL, surface->client->resource, ZXDG_SHELL_V6_ERROR_ROLE)) { + return NULL; + } + + popup = calloc(1, sizeof(struct ds_xdg_popup_v6)); + if (!popup) { + wl_resource_post_no_memory(surface->resource); + return NULL; + } + + popup->base = surface; + popup->parent = parent->ds_surface; + popup->resource = wl_resource_create(surface->client->wl_client, + &zxdg_popup_v6_interface, + wl_resource_get_version(surface->resource), id); + if (!popup->resource) { + free(popup); + wl_resource_post_no_memory(surface->resource); + return NULL; + } + wl_resource_set_implementation(popup->resource, + &xdg_popup_v6_impl, popup, xdg_popup_v6_handle_resource_destroy); + + // TODO get geometry from positioner + + ds_inf("Created ds_xdg_popup_v6(%p) with surface(%p), parent(%p)", + popup, surface->ds_surface, parent->ds_surface); + + return popup; +} + +void +destroy_xdg_popup_v6(struct ds_xdg_popup_v6 *popup) +{ + struct ds_xdg_popup_v6 *child, *child_tmp; + + ds_inf("Destroy ds_xdg_popup_v6(%p)", popup); + + wl_list_for_each_safe(child, child_tmp, &popup->base->popups, link) { + zxdg_popup_v6_send_popup_done(child->resource); + destroy_xdg_surface_v6_role(child->base); + } + + wl_resource_set_user_data(popup->resource, NULL); + + ds_surface_reset_role_data(popup->base->ds_surface); + wl_list_remove(&popup->link); + free(popup); +} + +void +reset_xdg_popup_v6(struct ds_xdg_popup_v6 *popup) +{ + ds_inf("Reset ds_xdg_popup_v6(%p)", popup); + + // TODO handle grab + + popup->committed = false; +} + +void +handle_xdg_popup_v6_committed(struct ds_xdg_popup_v6 *popup) +{ + if (!popup->committed) { + ds_xdg_surface_v6_schedule_configure(popup->base); + popup->committed = true; + } + + // TODO commit state +} + +void +send_xdg_popup_v6_configure(struct ds_xdg_surface_v6 *surface) +{ + struct ds_xdg_popup_v6 *popup = surface->popup; + + zxdg_popup_v6_send_configure(popup->resource, + popup->geometry.x, popup->geometry.y, + popup->geometry.width, popup->geometry.height); +} diff --git a/src/xdg_shell_v6/xdg_positioner_v6.c b/src/xdg_shell_v6/xdg_positioner_v6.c index 5eecf1a..d2f6877 100644 --- a/src/xdg_shell_v6/xdg_positioner_v6.c +++ b/src/xdg_shell_v6/xdg_positioner_v6.c @@ -69,9 +69,9 @@ xdg_positioner_v6_handle_set_anchor(struct wl_client *wl_client, struct ds_xdg_positioner_v6 *positioner; if (((anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP) && - (anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)) || - ((anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT) && - (anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT))) { + (anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)) || + ((anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT) && + (anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT))) { wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, "same-axis values are not allowed (%d)", anchor); @@ -90,9 +90,9 @@ xdg_positioner_v6_handle_set_gravity(struct wl_client *wl_client, struct ds_xdg_positioner_v6 *positioner; if (((gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP) && - (gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM)) || - ((gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT) && - (gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT))) { + (gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM)) || + ((gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT) && + (gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT))) { wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, "same-axis values are not allowed (%d)", gravity); diff --git a/src/xdg_shell_v6/xdg_shell_v6.h b/src/xdg_shell_v6/xdg_shell_v6.h index c4059a6..51a0fe1 100644 --- a/src/xdg_shell_v6/xdg_shell_v6.h +++ b/src/xdg_shell_v6/xdg_shell_v6.h @@ -60,4 +60,16 @@ void destroy_xdg_toplevel_v6(struct ds_xdg_toplevel_v6 *toplevel); void create_xdg_positioner_v6(struct ds_xdg_client_v6 *client, uint32_t id); +struct ds_xdg_popup_v6 *create_xdg_popup_v6(struct ds_xdg_surface_v6 *surface, + struct ds_xdg_surface_v6 *parent, + struct ds_xdg_positioner_v6 *positioner, uint32_t id); + +void destroy_xdg_popup_v6(struct ds_xdg_popup_v6 *popup); + +void reset_xdg_popup_v6(struct ds_xdg_popup_v6 *popup); + +void handle_xdg_popup_v6_committed(struct ds_xdg_popup_v6 *popup); + +void send_xdg_popup_v6_configure(struct ds_xdg_surface_v6 *surface); + #endif diff --git a/src/xdg_shell_v6/xdg_surface_v6.c b/src/xdg_shell_v6/xdg_surface_v6.c index fe7e2b4..13c699a 100644 --- a/src/xdg_shell_v6/xdg_surface_v6.c +++ b/src/xdg_shell_v6/xdg_surface_v6.c @@ -1,3 +1,4 @@ +#include #include #include "libds/log.h" @@ -77,6 +78,7 @@ create_xdg_surface_v6(struct ds_xdg_client_v6 *client, struct ds_surface *ds_sur } wl_list_init(&surface->configure_list); + wl_list_init(&surface->popups); wl_signal_init(&surface->events.destroy); wl_signal_init(&surface->events.ping_timeout); @@ -118,15 +120,20 @@ void reset_xdg_surface_v6(struct ds_xdg_surface_v6 *surface) { struct ds_xdg_surface_v6_configure *configure, *tmp; + struct ds_xdg_popup_v6 *popup, *popup_tmp; surface->configured = false; + wl_list_for_each_safe(popup, popup_tmp, &surface->popups, link) { + destroy_xdg_popup_v6(popup); + } + switch (surface->role) { case DS_XDG_SURFACE_V6_ROLE_TOPLEVEL: reset_xdg_toplevel_v6(surface->toplevel); break; case DS_XDG_SURFACE_V6_ROLE_POPUP: - // TODO + reset_xdg_popup_v6(surface->popup); break; case DS_XDG_SURFACE_V6_ROLE_NONE: break; @@ -174,7 +181,8 @@ destroy_xdg_surface_v6_role(struct ds_xdg_surface_v6 *surface) surface->toplevel = NULL; break; case DS_XDG_SURFACE_V6_ROLE_POPUP: - // TODO + destroy_xdg_popup_v6(surface->popup); + surface->popup = NULL; break; default: break; @@ -234,14 +242,15 @@ xdg_surface_v6_handle_surface_commit(struct wl_listener *listener, void *data) switch (surface->role) { case DS_XDG_SURFACE_V6_ROLE_NONE: - // inert toplevel or popup + wl_resource_post_error(surface->resource, + ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED, + "xdg_surface must have a role before commit"); break; case DS_XDG_SURFACE_V6_ROLE_TOPLEVEL: handle_xdg_toplevel_v6_committed(surface->toplevel); - // TODO break; case DS_XDG_SURFACE_V6_ROLE_POPUP: - // TODO + handle_xdg_popup_v6_committed(surface->popup); break; } @@ -308,12 +317,33 @@ xdg_surface_v6_handle_get_popup(struct wl_client *client, struct wl_resource *parent_resource, struct wl_resource *positioner_resource) { - struct ds_xdg_surface_v6 *surface; + struct ds_xdg_surface_v6 *surface, *parent; + struct ds_xdg_positioner_v6 *positioner; surface = wl_resource_get_user_data(resource); + if (surface->role != DS_XDG_SURFACE_V6_ROLE_NONE) { + wl_resource_post_error(surface->resource, + ZXDG_SURFACE_V6_ERROR_ALREADY_CONSTRUCTED, + "xdg-surface has already been constructed"); + return; + } + + positioner = wl_resource_get_user_data(positioner_resource); + if (positioner->size.width == 0 || positioner->anchor_rect.width == 0) { + wl_resource_post_error(surface->client->resource, + ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER, + "positioner object is not complete"); + return; + } + + assert(surface->popup == NULL); + + parent = wl_resource_get_user_data(parent_resource); + surface->popup = create_xdg_popup_v6(surface, parent, positioner, id); + surface->role = DS_XDG_SURFACE_V6_ROLE_POPUP; + wl_list_insert(&surface->popups, &surface->popup->link); - // TODO - (void)surface; + wl_signal_emit_mutable(&surface->events.new_popup, surface->popup); } static void @@ -438,6 +468,7 @@ surface_send_configure(void *user_data) send_xdg_toplevel_v6_configure(surface, configure); break; case DS_XDG_SURFACE_V6_ROLE_POPUP: + send_xdg_popup_v6_configure(surface); break; }