static void xdg_surface_destructor (struct wl_resource *resource) { MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); meta_wayland_compositor_destroy_frame_callbacks (surface->compositor, surface); meta_wayland_surface_destroy_window (surface); xdg_surface->resource = NULL; }
static void meta_wayland_wl_shell_surface_popup_dismiss (MetaWaylandPopupSurface *popup_surface) { MetaWaylandWlShellSurface *wl_shell_surface = META_WAYLAND_WL_SHELL_SURFACE (popup_surface); MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (popup_surface); MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); wl_shell_surface->popup = NULL; meta_wayland_surface_destroy_window (surface); }
static void handle_popup_parent_destroyed (struct wl_listener *listener, void *data) { MetaWaylandXdgPopup *xdg_popup = wl_container_of (listener, xdg_popup, parent_destroy_listener); MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (xdg_popup); MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); wl_resource_post_error (xdg_popup->xdg_shell_resource, XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP, "destroyed popup not top most popup"); xdg_popup->parent_surface = NULL; meta_wayland_surface_destroy_window (surface); }
static void wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role, MetaWaylandPendingState *pending) { MetaWaylandWlShellSurface *wl_shell_surface = META_WAYLAND_WL_SHELL_SURFACE (surface_role); MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); MetaWindow *window = surface->window; MetaRectangle geom = { 0 }; surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_wl_shell_surface_parent_class); surface_role_class->commit (surface_role, pending); /* For wl_shell, it's equivalent to an unmap. Semantics * are poorly defined, so we can choose some that are * convenient for us. */ if (surface->buffer_ref.buffer && !window) { create_wl_shell_surface_window (surface); } else if (!surface->buffer_ref.buffer && window) { if (wl_shell_surface->popup) meta_wayland_popup_dismiss (wl_shell_surface->popup); else meta_wayland_surface_destroy_window (surface); return; } if (!window) return; if (!pending->newly_attached) return; meta_wayland_surface_calculate_window_geometry (surface, &geom, 0, 0); meta_window_wayland_move_resize (window, NULL, geom, pending->dx, pending->dy); }
static void meta_wayland_xdg_popup_dismiss (MetaWaylandPopupSurface *popup_surface) { MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (popup_surface); MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (xdg_popup); MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); MetaWaylandSurface *top_popup; top_popup = meta_wayland_popup_get_top_popup (xdg_popup->popup); if (surface != top_popup) { wl_resource_post_error (xdg_popup->xdg_shell_resource, XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP, "destroyed popup not top most popup"); } xdg_popup->popup = NULL; meta_wayland_surface_destroy_window (surface); }
static void xdg_shell_get_xdg_popup (struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource, struct wl_resource *seat_resource, uint32_t serial, int32_t x, int32_t y) { MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandPopupSurface *popup_surface; MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); MetaWaylandSurface *top_popup; MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); MetaWindow *window; MetaDisplay *display = meta_get_display (); MetaWaylandXdgPopup *xdg_popup; MetaWaylandPopup *popup; if (META_IS_WAYLAND_XDG_POPUP (surface->role) && META_WAYLAND_XDG_POPUP (surface->role)->resource) { wl_resource_post_error (surface_resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "xdg_shell::get_xdg_popup already requested"); return; } if (!meta_wayland_surface_assign_role (surface, META_TYPE_WAYLAND_XDG_POPUP)) { wl_resource_post_error (resource, XDG_SHELL_ERROR_ROLE, "wl_surface@%d already has a different role", wl_resource_get_id (surface->resource)); return; } if (parent_surf == NULL || parent_surf->window == NULL || (!META_IS_WAYLAND_XDG_POPUP (parent_surf->role) && !META_IS_WAYLAND_XDG_SURFACE (parent_surf->role))) { wl_resource_post_error (resource, XDG_SHELL_ERROR_INVALID_POPUP_PARENT, "invalid parent surface"); return; } top_popup = meta_wayland_pointer_get_top_popup (&seat->pointer); if ((top_popup == NULL && !META_IS_WAYLAND_XDG_SURFACE (parent_surf->role)) || (top_popup != NULL && parent_surf != top_popup)) { wl_resource_post_error (resource, XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP, "parent not top most surface"); return; } xdg_popup = META_WAYLAND_XDG_POPUP (surface->role); xdg_popup->resource = wl_resource_create (client, &xdg_popup_interface, wl_resource_get_version (resource), id); wl_resource_set_implementation (xdg_popup->resource, &meta_wayland_xdg_popup_interface, xdg_popup, xdg_popup_destructor); xdg_popup->xdg_shell_resource = resource; if (!meta_wayland_seat_can_popup (seat, serial)) { xdg_popup_send_popup_done (xdg_popup->resource); return; } xdg_popup->parent_surface = parent_surf; xdg_popup->parent_destroy_listener.notify = handle_popup_parent_destroyed; wl_resource_add_destroy_listener (parent_surf->resource, &xdg_popup->parent_destroy_listener); window = meta_window_wayland_new (display, surface); meta_window_wayland_place_relative_to (window, parent_surf->window, x, y); window->showing_for_first_time = FALSE; meta_wayland_surface_set_window (surface, window); meta_window_focus (window, meta_display_get_current_time (display)); popup_surface = META_WAYLAND_POPUP_SURFACE (surface->role); popup = meta_wayland_pointer_start_popup_grab (&seat->pointer, popup_surface); if (popup == NULL) { xdg_popup_send_popup_done (xdg_popup->resource); meta_wayland_surface_destroy_window (surface); return; } xdg_popup->popup = popup; }