From bbe36418447f8d69d5beb8b1b9c5c9bf0f1f709a Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Thu, 14 Nov 2013 21:55:37 -0500 Subject: [PATCH] wayland-surface: Add support for xdg_popup --- src/wayland/meta-wayland-pointer.c | 8 ++--- src/wayland/meta-wayland-surface.c | 54 ++++++++++++++++++++++++++--- src/wayland/meta-wayland-surface.h | 1 + src/wayland/meta-wayland-versions.h | 1 + 4 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index 3540f747c..37748f129 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -538,14 +538,14 @@ meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer) wl_list_for_each_safe (popup, tmp, &popup_grab->all_popups, link) { - MetaWaylandSurfaceExtension *shell_surface = &popup->surface->xdg_surface; - struct wl_client *client = wl_resource_get_client (shell_surface->resource); + MetaWaylandSurfaceExtension *xdg_popup = &popup->surface->xdg_popup; + struct wl_client *client = wl_resource_get_client (xdg_popup->resource); struct wl_display *display = wl_client_get_display (client); uint32_t serial; serial = wl_display_next_serial (display); - xdg_popup_send_popup_done (shell_surface->resource, serial); + xdg_popup_send_popup_done (xdg_popup->resource, serial); wl_list_remove (&popup->surface_destroy_listener.link); wl_list_remove (&popup->link); g_slice_free (MetaWaylandPopup, popup); @@ -607,7 +607,7 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer, popup->grab = grab; popup->surface = surface; popup->surface_destroy_listener.notify = on_popup_surface_destroy; - wl_resource_add_destroy_listener (surface->resource, &popup->surface_destroy_listener); + wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener); wl_list_insert (&grab->all_popups, &popup->link); diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 83560511e..0f318e273 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -329,6 +329,7 @@ meta_wayland_surface_commit (struct wl_client *client, wl_list_remove (&surface->pending.buffer_destroy_listener.link); surface->pending.buffer = NULL; } + surface->pending.dx = 0; surface->pending.dy = 0; surface->pending.newly_attached = FALSE; @@ -759,19 +760,64 @@ get_xdg_surface (struct wl_client *client, surface->window = meta_window_new_for_wayland (meta_get_display (), surface); } +static void +xdg_popup_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + destroy_surface_extension (resource); +} + +static void +xdg_popup_pong (struct wl_client *client, + struct wl_resource *resource, + uint32_t serial) +{ +} + +static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = { + xdg_popup_destroy, + xdg_popup_pong, +}; + static void get_xdg_popup (struct wl_client *client, struct wl_resource *resource, uint32_t id, - struct wl_resource *surface, - struct wl_resource *parent, - struct wl_resource *seat, + struct wl_resource *surface_resource, + struct wl_resource *parent_resource, + struct wl_resource *seat_resource, uint32_t serial, int32_t x, int32_t y, uint32_t flags) { - g_warning ("TODO: support xdg_shell.get_xdg_popup"); + MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); + MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); + MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); + MetaRectangle parent_rect; + + if (parent_surf == NULL || parent_surf->window == NULL) + return; + + meta_window_get_frame_rect (parent_surf->window, &parent_rect); + + if (!create_surface_extension (&surface->xdg_popup, client, surface_resource, resource, id, + META_XDG_POPUP_VERSION, + &xdg_popup_interface, + &meta_wayland_xdg_popup_interface)) + wl_resource_post_error (surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "xdg_shell::get_xdg_surface already requested"); + + surface->window = meta_window_new_for_wayland (meta_get_display (), surface); + surface->window->type = META_WINDOW_DROPDOWN_MENU; + surface->window->override_redirect = TRUE; + surface->window->showing_for_first_time = FALSE; + surface->window->rect.x = parent_rect.x + x; + surface->window->rect.y = parent_rect.y + y; + surface->window->placed = TRUE; + + meta_wayland_pointer_start_popup_grab (&seat->pointer, surface); } static const struct xdg_shell_interface meta_wayland_xdg_shell_interface = { diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 62d2fdeb3..3d043cd12 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -79,6 +79,7 @@ struct _MetaWaylandSurface MetaWaylandBufferReference buffer_ref; MetaWindow *window; MetaWaylandSurfaceExtension xdg_surface; + MetaWaylandSurfaceExtension xdg_popup; MetaWaylandSurfaceExtension gtk_surface; /* All the pending state, that wl_surface.commit will apply. */ diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h index 37aa4e3ca..7e85f8b29 100644 --- a/src/wayland/meta-wayland-versions.h +++ b/src/wayland/meta-wayland-versions.h @@ -54,6 +54,7 @@ #define META_WL_REGION_VERSION 1 /* from wl_compositor */ #define META_GTK_SURFACE_VERSION 1 /* from gtk_shell */ #define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */ +#define META_XDG_POPUP_VERSION 1 /* from xdg_shell */ /* The first version to implement a specific event */ #define META_WL_SEAT_HAS_NAME 2