diff options
-rw-r--r-- | include/wlr/types/wlr_xdg_shell_v6.h | 18 | ||||
-rw-r--r-- | rootston/desktop.c | 53 | ||||
-rw-r--r-- | rootston/output.c | 23 | ||||
-rw-r--r-- | rootston/xdg_shell_v6.c | 11 | ||||
-rw-r--r-- | types/wlr_xdg_shell_v6.c | 409 |
5 files changed, 460 insertions, 54 deletions
diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index cc52d9c7..b7acc2c4 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -28,6 +28,15 @@ struct wlr_xdg_client_v6 { struct wl_event_source *ping_timer; }; +struct wlr_xdg_popup_v6 { + struct wlr_xdg_surface_v6 *base; + + struct wl_resource *resource; + bool committed; + struct wlr_xdg_surface_v6 *parent; + struct wlr_seat *seat; + struct wlr_box geometry; +}; enum wlr_xdg_surface_v6_role { WLR_XDG_SURFACE_V6_ROLE_NONE, @@ -74,7 +83,14 @@ struct wlr_xdg_surface_v6 { struct wlr_surface *surface; struct wl_list link; // wlr_xdg_client_v6::surfaces enum wlr_xdg_surface_v6_role role; - struct wlr_xdg_toplevel_v6 *toplevel_state; + + union { + struct wlr_xdg_toplevel_v6 *toplevel_state; + struct wlr_xdg_popup_v6 *popup_state; + }; + + struct wl_list popups; + struct wl_list popup_link; bool configured; struct wl_event_source *configure_idle; diff --git a/rootston/desktop.c b/rootston/desktop.c index 8d1d34d6..2c4611a8 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -40,6 +40,15 @@ void view_get_input_bounds(struct roots_view *view, struct wlr_box *box) { view->get_input_bounds(view, box); return; } + + if (view->type == ROOTS_XDG_SHELL_V6_VIEW) { + box->x = view->xdg_surface_v6->geometry->x; + box->y = view->xdg_surface_v6->geometry->y; + box->width = view->xdg_surface_v6->geometry->width; + box->height = view->xdg_surface_v6->geometry->height; + return; + } + box->x = box->y = 0; box->width = view->wlr_surface->current->width; box->height = view->wlr_surface->current->height; @@ -84,6 +93,36 @@ static struct wlr_subsurface *subsurface_at(struct wlr_surface *surface, return NULL; } +static struct wlr_xdg_surface_v6 *xdg_v6_popup_at( + struct wlr_xdg_surface_v6 *surface, double sx, double sy, + double *popup_sx, double *popup_sy) { + struct wlr_xdg_surface_v6 *popup; + wl_list_for_each(popup, &surface->popups, popup_link) { + double _popup_sx = surface->geometry->x + popup->popup_state->geometry.x; + double _popup_sy = surface->geometry->y + popup->popup_state->geometry.y; + int popup_width = popup->popup_state->geometry.width; + int popup_height = popup->popup_state->geometry.height; + + struct wlr_xdg_surface_v6 *_popup = + xdg_v6_popup_at(popup, sx - _popup_sx + popup->geometry->x, + sy - _popup_sy + popup->geometry->y, popup_sx, popup_sy); + if (_popup) { + *popup_sx = *popup_sx + _popup_sx - popup->geometry->x; + *popup_sy = *popup_sy + _popup_sy - popup->geometry->y; + return _popup; + } + + if ((sx > _popup_sx && sx < _popup_sx + popup_width) && + (sy > _popup_sy && sy < _popup_sy + popup_height)) { + *popup_sx = _popup_sx - popup->geometry->x; + *popup_sy = _popup_sy - popup->geometry->y; + return popup; + } + } + + return NULL; +} + struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { for (int i = desktop->views->length - 1; i >= 0; --i) { @@ -92,6 +131,20 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, double view_sx = lx - view->x; double view_sy = ly - view->y; + if (view->type == ROOTS_XDG_SHELL_V6_VIEW) { + double popup_sx, popup_sy; + struct wlr_xdg_surface_v6 *popup = + xdg_v6_popup_at(view->xdg_surface_v6, view_sx, view_sy, + &popup_sx, &popup_sy); + + if (popup) { + *sx = view_sx - popup_sx; + *sy = view_sy - popup_sy; + *surface = popup->surface; + return view; + } + } + double sub_x, sub_y; struct wlr_subsurface *subsurface = subsurface_at(view->wlr_surface, view_sx, view_sy, &sub_x, &sub_y); diff --git a/rootston/output.c b/rootston/output.c index 14d1783e..06786395 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -53,10 +53,33 @@ static void render_surface(struct wlr_surface *surface, } } +static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, + struct roots_desktop *desktop, struct wlr_output *wlr_output, + struct timespec *when, double base_x, double base_y) { + struct wlr_xdg_surface_v6 *popup; + wl_list_for_each(popup, &surface->popups, popup_link) { + if (!popup->configured) { + continue; + } + + double popup_x = base_x + surface->geometry->x + + popup->popup_state->geometry.x - popup->geometry->x; + double popup_y = base_y + surface->geometry->y + + popup->popup_state->geometry.y - popup->geometry->y; + render_surface(popup->surface, desktop, wlr_output, when, popup_x, + popup_y); + render_xdg_v6_popups(popup, desktop, wlr_output, when, popup_x, popup_y); + } +} + static void render_view(struct roots_view *view, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when) { render_surface(view->wlr_surface, desktop, wlr_output, when, view->x, view->y); + if (view->type == ROOTS_XDG_SHELL_V6_VIEW) { + render_xdg_v6_popups(view->xdg_surface_v6, desktop, wlr_output, + when, view->x, view->y); + } } static void output_frame_notify(struct wl_listener *listener, void *data) { diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index ab34f52a..ff0dd090 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -73,11 +73,18 @@ static void handle_destroy(struct wl_listener *listener, void *data) { } void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { + struct wlr_xdg_surface_v6 *surface = data; + assert(surface->role != WLR_XDG_SURFACE_V6_ROLE_NONE); + + if (surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { + wlr_log(L_DEBUG, "new xdg popup"); + return; + } + struct roots_desktop *desktop = wl_container_of(listener, desktop, xdg_shell_v6_surface); - struct wlr_xdg_surface_v6 *surface = data; - wlr_log(L_DEBUG, "new xdg surface: title=%s, app_id=%s", + wlr_log(L_DEBUG, "new xdg toplevel: title=%s, app_id=%s", surface->title, surface->app_id); wlr_xdg_surface_v6_ping(surface); diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index c30291d1..6e32ebdf 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -12,12 +12,323 @@ #include "xdg-shell-unstable-v6-protocol.h" static const char *wlr_desktop_xdg_toplevel_role = "xdg_toplevel"; +static const char *wlr_desktop_xdg_popup_role = "xdg_popup"; + +struct wlr_xdg_positioner_v6 { + struct wl_resource *resource; + + struct wlr_box anchor_rect; + enum zxdg_positioner_v6_anchor anchor; + enum zxdg_positioner_v6_gravity gravity; + enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment; + + struct { + int32_t width, height; + } size; + + struct { + int32_t x, y; + } offset; +}; + static void resource_destroy(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); } +static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) { + wl_signal_emit(&surface->events.destroy, surface); + wl_resource_set_user_data(surface->resource, NULL); + + if (surface->configure_idle) { + wl_event_source_remove(surface->configure_idle); + } + + struct wlr_xdg_surface_v6_configure *configure, *tmp; + wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) { + free(configure); + } + + if (surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { + wl_resource_set_user_data(surface->toplevel_state->resource, NULL); + free(surface->toplevel_state); + } + + if (surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { + wl_resource_set_user_data(surface->popup_state->resource, NULL); + wl_list_remove(&surface->popup_link); + free(surface->popup_state); + } + + wl_list_remove(&surface->link); + wl_list_remove(&surface->surface_destroy_listener.link); + wl_list_remove(&surface->surface_commit_listener.link); + free(surface->geometry); + free(surface->next_geometry); + free(surface->title); + free(surface->app_id); + free(surface); +} + + +static void xdg_positioner_destroy(struct wl_resource *resource) { + struct wlr_xdg_positioner_v6 *positioner = + wl_resource_get_user_data(resource); + free(positioner); + +} + +static void xdg_positioner_protocol_set_size(struct wl_client *client, + struct wl_resource *resource, int32_t width, int32_t height) { + struct wlr_xdg_positioner_v6 *positioner = + wl_resource_get_user_data(resource); + + if (width < 1 || height < 1) { + wl_resource_post_error(resource, + ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, + "width and height must be positives and non-zero"); + return; + } + + positioner->size.width = width; + positioner->size.height = height; +} + +static void xdg_positioner_protocol_set_anchor_rect(struct wl_client *client, + struct wl_resource *resource, int32_t x, int32_t y, int32_t width, + int32_t height) { + struct wlr_xdg_positioner_v6 *positioner = + wl_resource_get_user_data(resource); + + if (width < 1 || height < 1) { + wl_resource_post_error(resource, + ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, + "width and height must be positives and non-zero"); + return; + } + + positioner->anchor_rect.x = x; + positioner->anchor_rect.y = y; + positioner->anchor_rect.width = width; + positioner->anchor_rect.height = height; +} + +static void xdg_positioner_protocol_set_anchor(struct wl_client *client, + struct wl_resource *resource, uint32_t anchor) { + struct wlr_xdg_positioner_v6 *positioner = + wl_resource_get_user_data(resource); + + 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))) { + wl_resource_post_error(resource, + ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, + "same-axis values are not allowed"); + return; + } + + positioner->anchor = anchor; +} + +static void xdg_positioner_protocol_set_gravity(struct wl_client *client, + struct wl_resource *resource, uint32_t gravity) { + struct wlr_xdg_positioner_v6 *positioner = + wl_resource_get_user_data(resource); + + 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))) { + wl_resource_post_error(resource, + ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, + "same-axis values are not allowed"); + return; + } + + positioner->gravity = gravity; +} + +static void xdg_positioner_protocol_set_constraint_adjustment( + struct wl_client *client, struct wl_resource *resource, + uint32_t constraint_adjustment) { + struct wlr_xdg_positioner_v6 *positioner = + wl_resource_get_user_data(resource); + + positioner->constraint_adjustment = constraint_adjustment; +} + +static void xdg_positioner_protocol_set_offset(struct wl_client *client, + struct wl_resource *resource, int32_t x, int32_t y) { + struct wlr_xdg_positioner_v6 *positioner = + wl_resource_get_user_data(resource); + + positioner->offset.x = x; + positioner->offset.y = y; +} + +static const struct zxdg_positioner_v6_interface zxdg_positioner_v6_implementation = { + .destroy = resource_destroy, + .set_size = xdg_positioner_protocol_set_size, + .set_anchor_rect = xdg_positioner_protocol_set_anchor_rect, + .set_anchor = xdg_positioner_protocol_set_anchor, + .set_gravity = xdg_positioner_protocol_set_gravity, + .set_constraint_adjustment = + xdg_positioner_protocol_set_constraint_adjustment, + .set_offset = xdg_positioner_protocol_set_offset, +}; + +static void xdg_shell_create_positioner(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t id) { + struct wlr_xdg_positioner_v6 *positioner = + calloc(1, sizeof(struct wlr_xdg_positioner_v6)); + if (positioner == NULL) { + wl_client_post_no_memory(wl_client); + return; + } + + positioner->resource = wl_resource_create(wl_client, + &zxdg_positioner_v6_interface, + wl_resource_get_version(resource), + id); + if (positioner->resource == NULL) { + wl_client_post_no_memory(wl_client); + free(positioner); + return; + } + + wl_resource_set_implementation(positioner->resource, + &zxdg_positioner_v6_implementation, + positioner, xdg_positioner_destroy); +} + +static void xdg_popup_protocol_grab(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *seat_resource, + uint32_t serial) { + wlr_log(L_DEBUG, "TODO: xdg popup grab"); +} + +static const struct zxdg_popup_v6_interface zxdg_popup_v6_implementation = { + .destroy = resource_destroy, + .grab = xdg_popup_protocol_grab, +}; + + +static struct wlr_box xdg_positioner_get_geometry( + struct wlr_xdg_positioner_v6 *positioner, + struct wlr_xdg_surface_v6 *surface, struct wlr_xdg_surface_v6 *parent) { + struct wlr_box geometry = { + .x = positioner->offset.x, + .y = positioner->offset.y, + .width = positioner->size.width, + .height = positioner->size.height, + }; + + if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP) { + geometry.y += positioner->anchor_rect.y; + } else if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM) { + geometry.y += + positioner->anchor_rect.y + positioner->anchor_rect.height; + } else { + geometry.y += + positioner->anchor_rect.y + positioner->anchor_rect.height / 2; + } + + if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT) { + geometry.x += positioner->anchor_rect.x; + } else if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT) { + geometry.x += positioner->anchor_rect.x + positioner->anchor_rect.width; + } else { + geometry.x += + positioner->anchor_rect.x + positioner->anchor_rect.width / 2; + } + + if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP) { + geometry.y -= geometry.height; + } else if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM) { + geometry.y = geometry.y; + } else { + geometry.y -= geometry.height / 2; + } + + if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT) { + geometry.x -= geometry.width; + } else if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT) { + geometry.x = geometry.x; + } else { + geometry.x -= geometry.width / 2; + } + + if (positioner->constraint_adjustment == + ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE) { + return geometry; + } + + // TODO: add compositor policy configuration and the code here + + return geometry; +} + +static void xdg_popup_resource_destroy(struct wl_resource *resource) { + struct wlr_xdg_surface_v6 *surface = wl_resource_get_user_data(resource); + if (surface != NULL) { + xdg_surface_destroy(surface); + } +} + +static void xdg_surface_get_popup(struct wl_client *client, + struct wl_resource *resource, uint32_t id, + struct wl_resource *parent_resource, + struct wl_resource *positioner_resource) { + struct wlr_xdg_surface_v6 *surface = + wl_resource_get_user_data(resource); + struct wlr_xdg_surface_v6 *parent = + wl_resource_get_user_data(parent_resource); + struct wlr_xdg_positioner_v6 *positioner = + wl_resource_get_user_data(positioner_resource); + + if (positioner->size.width == 0 || positioner->anchor_rect.width == 0) { + wl_resource_post_error(resource, + ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER, + "positioner object is not complete"); + return; + } + + if (wlr_surface_set_role(surface->surface, wlr_desktop_xdg_popup_role, + resource, ZXDG_SHELL_V6_ERROR_ROLE)) { + return; + } + + surface->popup_state = calloc(1, sizeof(struct wlr_xdg_popup_v6)); + if (!surface->popup_state) { + wl_client_post_no_memory(client); + return; + } + + surface->popup_state->resource = + wl_resource_create(client, &zxdg_popup_v6_interface, + wl_resource_get_version(resource), id); + if (surface->popup_state->resource == NULL) { + free(surface->popup_state); + return; + } + + surface->role = WLR_XDG_SURFACE_V6_ROLE_POPUP; + surface->popup_state->parent = parent; + surface->popup_state->geometry = + xdg_positioner_get_geometry(positioner, surface, parent); + wl_list_insert(&surface->popup_state->parent->popups, + &surface->popup_link); + + wl_resource_set_implementation(surface->popup_state->resource, + &zxdg_popup_v6_implementation, surface, + xdg_popup_resource_destroy); + + // TODO: set relative to parent? +} + + static void xdg_toplevel_protocol_set_parent(struct wl_client *client, struct wl_resource *resource, struct wl_resource *parent_resource) { struct wlr_xdg_surface_v6 *surface = wl_resource_get_user_data(resource); @@ -216,34 +527,6 @@ static const struct zxdg_toplevel_v6_interface zxdg_toplevel_v6_implementation = .set_minimized = xdg_toplevel_protocol_set_minimized }; -static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) { - wl_signal_emit(&surface->events.destroy, surface); - wl_resource_set_user_data(surface->resource, NULL); - - if (surface->configure_idle) { - wl_event_source_remove(surface->configure_idle); - } - - struct wlr_xdg_surface_v6_configure *configure, *tmp; - wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) { - free(configure); - } - - if (surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { - wl_resource_set_user_data(surface->toplevel_state->resource, NULL); - free(surface->toplevel_state); - } - - wl_list_remove(&surface->link); - wl_list_remove(&surface->surface_destroy_listener.link); - wl_list_remove(&surface->surface_commit_listener.link); - free(surface->geometry); - free(surface->next_geometry); - free(surface->title); - free(surface->app_id); - free(surface); -} - static void xdg_surface_resource_destroy(struct wl_resource *resource) { struct wlr_xdg_surface_v6 *surface = wl_resource_get_user_data(resource); if (surface != NULL) { @@ -286,12 +569,6 @@ static void xdg_surface_get_toplevel(struct wl_client *client, xdg_toplevel_resource_destroy); } -static void xdg_surface_get_popup(struct wl_client *client, - struct wl_resource *resource, uint32_t id, struct wl_resource *parent, - struct wl_resource *wl_positioner) { - wlr_log(L_DEBUG, "TODO xdg surface get popup"); -} - static void wlr_xdg_toplevel_v6_ack_configure( struct wlr_xdg_surface_v6 *surface, struct wlr_xdg_surface_v6_configure *configure) { @@ -333,9 +610,15 @@ static void xdg_surface_ack_configure(struct wl_client *client, return; } - // TODO handle popups - if (surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { + switch (surface->role) { + case WLR_XDG_SURFACE_V6_ROLE_NONE: + assert(0 && "not reached"); + break; + case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL: wlr_xdg_toplevel_v6_ack_configure(surface, configure); + break; + case WLR_XDG_SURFACE_V6_ROLE_POPUP: + break; } if (!surface->configured) { @@ -376,11 +659,6 @@ static const struct zxdg_surface_v6_interface zxdg_surface_v6_implementation = { .set_window_geometry = xdg_surface_set_window_geometry, }; -static void xdg_shell_create_positioner(struct wl_client *client, - struct wl_resource *resource, uint32_t id) { - wlr_log(L_DEBUG, "TODO: xdg shell create positioner"); -} - static bool wlr_xdg_surface_v6_toplevel_state_compare( struct wlr_xdg_toplevel_v6 *state) { // is pending state different from current state? @@ -454,9 +732,6 @@ static void wlr_xdg_surface_send_configure(void *user_data) { struct wlr_xdg_surface_v6 *surface = user_data; struct wl_display *display = wl_client_get_display(surface->client->client); - // TODO handle popups - assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); - surface->configure_idle = NULL; struct wlr_xdg_surface_v6_configure *configure = @@ -469,21 +744,42 @@ static void wlr_xdg_surface_send_configure(void *user_data) { wl_list_insert(surface->configure_list.prev, &configure->link); configure->serial = wl_display_next_serial(display); - wlr_xdg_toplevel_v6_send_configure(surface, configure); + switch (surface->role) { + case WLR_XDG_SURFACE_V6_ROLE_NONE: + assert(0 && "not reached"); + break; + case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL: + wlr_xdg_toplevel_v6_send_configure(surface, configure); + break; + case WLR_XDG_SURFACE_V6_ROLE_POPUP: + zxdg_popup_v6_send_configure(surface->popup_state->resource, + surface->popup_state->geometry.x, + surface->popup_state->geometry.y, + surface->popup_state->geometry.width, + surface->popup_state->geometry.height); + break; + } zxdg_surface_v6_send_configure(surface->resource, configure->serial); } static void wlr_xdg_surface_v6_schedule_configure( struct wlr_xdg_surface_v6 *surface, bool force) { - // TODO handle popups - assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); - struct wl_display *display = wl_client_get_display(surface->client->client); struct wl_event_loop *loop = wl_display_get_event_loop(display); + bool pending_same = false; - bool pending_same = !force && - wlr_xdg_surface_v6_toplevel_state_compare(surface->toplevel_state); + switch (surface->role) { + case WLR_XDG_SURFACE_V6_ROLE_NONE: + assert(0 && "not reached"); + break; + case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL: + pending_same = !force && + wlr_xdg_surface_v6_toplevel_state_compare(surface->toplevel_state); + break; + case WLR_XDG_SURFACE_V6_ROLE_POPUP: + break; + } if (surface->configure_idle != NULL) { if (!pending_same) { @@ -534,6 +830,16 @@ static void wlr_xdg_surface_v6_toplevel_committed( surface->toplevel_state->current = surface->toplevel_state->next; } +static void wlr_xdg_surface_v6_popup_committed( + struct wlr_xdg_surface_v6 *surface) { + assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP); + + if (!surface->popup_state->committed) { + wlr_xdg_surface_v6_schedule_configure(surface, true); + surface->popup_state->committed = true; + } +} + static void handle_wlr_surface_committed(struct wl_listener *listener, void *data) { struct wlr_xdg_surface_v6 *surface = @@ -564,7 +870,7 @@ static void handle_wlr_surface_committed(struct wl_listener *listener, wlr_xdg_surface_v6_toplevel_committed(surface); break; case WLR_XDG_SURFACE_V6_ROLE_POPUP: - wlr_log(L_DEBUG, "TODO: popup surface committed"); + wlr_xdg_surface_v6_popup_committed(surface); break; } @@ -611,6 +917,7 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client, } wl_list_init(&surface->configure_list); + wl_list_init(&surface->popups); wl_signal_init(&surface->events.request_minimize); wl_signal_init(&surface->events.request_move); |