wayland: Move shell surface role fields to the role structs

Don't keep all the role specific fields in MetaWaylandSurface and have
the roles manage the needed fields themself.

https://bugzilla.gnome.org/show_bug.cgi?id=763431
This commit is contained in:
Jonas Ådahl 2016-01-22 14:22:40 +08:00
parent a89aa1d8cc
commit f318ec9df5
4 changed files with 352 additions and 251 deletions

View File

@ -1144,14 +1144,8 @@ wl_surface_destructor (struct wl_resource *resource)
if (surface->resource) if (surface->resource)
wl_resource_set_user_data (surface->resource, NULL); wl_resource_set_user_data (surface->resource, NULL);
if (surface->xdg_surface)
wl_resource_destroy (surface->xdg_surface);
if (surface->xdg_popup)
wl_resource_destroy (surface->xdg_popup);
if (surface->wl_subsurface) if (surface->wl_subsurface)
wl_resource_destroy (surface->wl_subsurface); wl_resource_destroy (surface->wl_subsurface);
if (surface->wl_shell_surface)
wl_resource_destroy (surface->wl_shell_surface);
if (surface->gtk_surface) if (surface->gtk_surface)
wl_resource_destroy (surface->gtk_surface); wl_resource_destroy (surface->gtk_surface);

View File

@ -158,16 +158,6 @@ struct _MetaWaylandDragDestFuncs
MetaWaylandSurface *surface); MetaWaylandSurface *surface);
}; };
typedef enum
{
META_WL_SHELL_SURFACE_STATE_NONE,
META_WL_SHELL_SURFACE_STATE_TOPLEVEL,
META_WL_SHELL_SURFACE_STATE_POPUP,
META_WL_SHELL_SURFACE_STATE_TRANSIENT,
META_WL_SHELL_SURFACE_STATE_FULLSCREEN,
META_WL_SHELL_SURFACE_STATE_MAXIMIZED,
} MetaWlShellSurfaceState;
struct _MetaWaylandSurface struct _MetaWaylandSurface
{ {
GObject parent; GObject parent;
@ -212,43 +202,12 @@ struct _MetaWaylandSurface
MetaWaylandPendingState *pending; MetaWaylandPendingState *pending;
/* Extension resources. */ /* Extension resources. */
struct wl_resource *xdg_surface;
struct wl_resource *xdg_popup;
struct wl_resource *wl_shell_surface;
struct wl_resource *gtk_surface; struct wl_resource *gtk_surface;
struct wl_resource *wl_subsurface; struct wl_resource *wl_subsurface;
/* xdg_surface stuff */ /* gtk_surface stuff */
struct wl_resource *xdg_shell_resource;
MetaWaylandSerial acked_configure_serial;
gboolean has_set_geometry;
gboolean is_modal; gboolean is_modal;
/* xdg_popup */
struct {
MetaWaylandSurface *parent;
struct wl_listener parent_destroy_listener;
MetaWaylandPopup *popup;
} popup;
/* wl_shell_surface */
struct {
MetaWlShellSurfaceState state;
char *title;
char *wm_class;
gboolean pending_popup;
MetaWaylandSurface *parent_surface;
GList *children;
MetaWaylandSeat *popup_seat;
int x;
int y;
} wl_shell;
/* wl_subsurface stuff. */ /* wl_subsurface stuff. */
struct { struct {
MetaWaylandSurface *parent; MetaWaylandSurface *parent;

View File

@ -34,9 +34,36 @@
#include "wayland/meta-wayland-versions.h" #include "wayland/meta-wayland-versions.h"
#include "wayland/meta-window-wayland.h" #include "wayland/meta-window-wayland.h"
typedef enum
{
META_WL_SHELL_SURFACE_STATE_NONE,
META_WL_SHELL_SURFACE_STATE_TOPLEVEL,
META_WL_SHELL_SURFACE_STATE_POPUP,
META_WL_SHELL_SURFACE_STATE_TRANSIENT,
META_WL_SHELL_SURFACE_STATE_FULLSCREEN,
META_WL_SHELL_SURFACE_STATE_MAXIMIZED,
} MetaWlShellSurfaceState;
struct _MetaWaylandWlShellSurface struct _MetaWaylandWlShellSurface
{ {
MetaWaylandSurfaceRoleShellSurface parent; MetaWaylandSurfaceRoleShellSurface parent;
struct wl_resource *resource;
MetaWlShellSurfaceState state;
char *title;
char *wm_class;
MetaWaylandSurface *parent_surface;
GList *children;
MetaWaylandSeat *popup_seat;
MetaWaylandPopup *popup;
gboolean pending_popup;
int x;
int y;
}; };
static void static void
@ -48,6 +75,17 @@ G_DEFINE_TYPE_WITH_CODE (MetaWaylandWlShellSurface,
G_IMPLEMENT_INTERFACE (META_TYPE_WAYLAND_POPUP_SURFACE, G_IMPLEMENT_INTERFACE (META_TYPE_WAYLAND_POPUP_SURFACE,
popup_surface_iface_init)); popup_surface_iface_init));
static MetaWaylandSurface *
surface_from_wl_shell_surface_resource (struct wl_resource *resource)
{
MetaWaylandWlShellSurface *wl_shell_surface =
wl_resource_get_user_data (resource);
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (wl_shell_surface);
return meta_wayland_surface_role_get_surface (surface_role);
}
static void static void
sync_wl_shell_parent_relationship (MetaWaylandSurface *surface, sync_wl_shell_parent_relationship (MetaWaylandSurface *surface,
MetaWaylandSurface *parent); MetaWaylandSurface *parent);
@ -55,47 +93,54 @@ sync_wl_shell_parent_relationship (MetaWaylandSurface *surface,
static void static void
wl_shell_surface_destructor (struct wl_resource *resource) wl_shell_surface_destructor (struct wl_resource *resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (wl_resource_get_user_data (resource));
MetaWaylandSurface *surface =
surface_from_wl_shell_surface_resource (resource);
GList *l; GList *l;
meta_wayland_compositor_destroy_frame_callbacks (surface->compositor, meta_wayland_compositor_destroy_frame_callbacks (surface->compositor,
surface); surface);
if (surface->popup.popup) if (wl_shell_surface->popup)
meta_wayland_popup_dismiss (surface->popup.popup); meta_wayland_popup_dismiss (wl_shell_surface->popup);
for (l = surface->wl_shell.children; l; l = l->next) for (l = wl_shell_surface->children; l; l = l->next)
{ {
MetaWaylandSurface *child_surface = l->data; MetaWaylandSurface *child_surface = l->data;
MetaWaylandWlShellSurface *child_wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (child_surface->role);
child_surface->wl_shell.parent_surface = NULL; child_wl_shell_surface->parent_surface = NULL;
if (child_surface->popup.parent == surface) if (child_wl_shell_surface->parent_surface == surface)
{ {
meta_wayland_popup_dismiss (child_surface->popup.popup); meta_wayland_popup_dismiss (child_wl_shell_surface->popup);
child_surface->popup.parent = NULL; child_wl_shell_surface->parent_surface = NULL;
} }
} }
if (surface->wl_shell.parent_surface) if (wl_shell_surface->parent_surface)
{ {
MetaWaylandSurface *parent_surface = surface->wl_shell.parent_surface; MetaWaylandSurface *parent_surface = wl_shell_surface->parent_surface;
MetaWaylandWlShellSurface *parent_wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (parent_surface->role);
parent_surface->wl_shell.children = parent_wl_shell_surface->children =
g_list_remove (parent_surface->wl_shell.children, surface); g_list_remove (parent_wl_shell_surface->children, surface);
} }
g_free (surface->wl_shell.title); g_free (wl_shell_surface->title);
g_free (surface->wl_shell.wm_class); g_free (wl_shell_surface->wm_class);
if (surface->popup.popup) if (wl_shell_surface->popup)
{ {
surface->popup.parent = NULL; wl_shell_surface->parent_surface = NULL;
meta_wayland_popup_dismiss (surface->popup.popup); meta_wayland_popup_dismiss (wl_shell_surface->popup);
} }
surface->wl_shell_surface = NULL; wl_shell_surface->resource = NULL;
} }
static void static void
@ -115,7 +160,8 @@ wl_shell_surface_move (struct wl_client *client,
uint32_t serial) uint32_t serial)
{ {
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface =
surface_from_wl_shell_surface_resource (resource);
gfloat x, y; gfloat x, y;
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y)) if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y))
@ -155,7 +201,8 @@ wl_shell_surface_resize (struct wl_client *client,
uint32_t edges) uint32_t edges)
{ {
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface =
surface_from_wl_shell_surface_resource (resource);
gfloat x, y; gfloat x, y;
MetaGrabOp grab_op; MetaGrabOp grab_op;
@ -170,17 +217,19 @@ static void
wl_shell_surface_set_state (MetaWaylandSurface *surface, wl_shell_surface_set_state (MetaWaylandSurface *surface,
MetaWlShellSurfaceState state) MetaWlShellSurfaceState state)
{ {
MetaWlShellSurfaceState old_state = surface->wl_shell.state; MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (surface->role);
MetaWlShellSurfaceState old_state = wl_shell_surface->state;
surface->wl_shell.state = state; wl_shell_surface->state = state;
if (surface->window && old_state != state) if (surface->window && old_state != state)
{ {
if (old_state == META_WL_SHELL_SURFACE_STATE_POPUP && if (old_state == META_WL_SHELL_SURFACE_STATE_POPUP &&
surface->popup.popup) wl_shell_surface->popup)
{ {
meta_wayland_popup_dismiss (surface->popup.popup); meta_wayland_popup_dismiss (wl_shell_surface->popup);
surface->popup.popup = NULL; wl_shell_surface->popup = NULL;
} }
if (state == META_WL_SHELL_SURFACE_STATE_FULLSCREEN) if (state == META_WL_SHELL_SURFACE_STATE_FULLSCREEN)
@ -199,7 +248,8 @@ static void
wl_shell_surface_set_toplevel (struct wl_client *client, wl_shell_surface_set_toplevel (struct wl_client *client,
struct wl_resource *resource) struct wl_resource *resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface =
surface_from_wl_shell_surface_resource (resource);
wl_shell_surface_set_state (surface, wl_shell_surface_set_state (surface,
META_WL_SHELL_SURFACE_STATE_TOPLEVEL); META_WL_SHELL_SURFACE_STATE_TOPLEVEL);
@ -209,17 +259,22 @@ static void
set_wl_shell_surface_parent (MetaWaylandSurface *surface, set_wl_shell_surface_parent (MetaWaylandSurface *surface,
MetaWaylandSurface *parent) MetaWaylandSurface *parent)
{ {
MetaWaylandSurface *old_parent = surface->wl_shell.parent_surface; MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (surface->role);
MetaWaylandWlShellSurface *parent_wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (parent->role);
if (old_parent) if (wl_shell_surface->parent_surface)
{ {
old_parent->wl_shell.children = MetaWaylandWlShellSurface *old_parent =
g_list_remove (old_parent->wl_shell.children, surface); META_WAYLAND_WL_SHELL_SURFACE (wl_shell_surface->parent_surface->role);
old_parent->children = g_list_remove (old_parent->children, surface);
} }
parent->wl_shell.children = g_list_append (parent->wl_shell.children, parent_wl_shell_surface->children =
surface); g_list_append (parent_wl_shell_surface->children, surface);
surface->wl_shell.parent_surface = parent; wl_shell_surface->parent_surface = parent;
} }
static void static void
@ -230,15 +285,18 @@ wl_shell_surface_set_transient (struct wl_client *client,
int32_t y, int32_t y,
uint32_t flags) uint32_t flags)
{ {
MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (wl_resource_get_user_data (resource));
MetaWaylandSurface *surface =
surface_from_wl_shell_surface_resource (resource);
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
wl_shell_surface_set_state (surface, wl_shell_surface_set_state (surface,
META_WL_SHELL_SURFACE_STATE_TRANSIENT); META_WL_SHELL_SURFACE_STATE_TRANSIENT);
set_wl_shell_surface_parent (surface, parent_surf); set_wl_shell_surface_parent (surface, parent_surf);
surface->wl_shell.x = x; wl_shell_surface->x = x;
surface->wl_shell.y = y; wl_shell_surface->y = y;
if (surface->window && parent_surf->window) if (surface->window && parent_surf->window)
sync_wl_shell_parent_relationship (surface, parent_surf); sync_wl_shell_parent_relationship (surface, parent_surf);
@ -251,30 +309,29 @@ wl_shell_surface_set_fullscreen (struct wl_client *client,
uint32_t framerate, uint32_t framerate,
struct wl_resource *output) struct wl_resource *output)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface =
surface_from_wl_shell_surface_resource (resource);
wl_shell_surface_set_state (surface, wl_shell_surface_set_state (surface,
META_WL_SHELL_SURFACE_STATE_FULLSCREEN); META_WL_SHELL_SURFACE_STATE_FULLSCREEN);
} }
static void static void
create_popup (MetaWaylandSurface *surface) meta_wayland_wl_shell_surface_create_popup (MetaWaylandWlShellSurface *wl_shell_surface)
{ {
MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (surface->role);
MetaWaylandPopupSurface *popup_surface = MetaWaylandPopupSurface *popup_surface =
META_WAYLAND_POPUP_SURFACE (wl_shell_surface); META_WAYLAND_POPUP_SURFACE (wl_shell_surface);
MetaWaylandSeat *seat = surface->wl_shell.popup_seat; MetaWaylandSeat *seat = wl_shell_surface->popup_seat;
MetaWaylandPopup *popup; MetaWaylandPopup *popup;
popup = meta_wayland_pointer_start_popup_grab (&seat->pointer, popup_surface); popup = meta_wayland_pointer_start_popup_grab (&seat->pointer, popup_surface);
if (!popup) if (!popup)
{ {
wl_shell_surface_send_popup_done (surface->wl_shell_surface); wl_shell_surface_send_popup_done (wl_shell_surface->resource);
return; return;
} }
surface->popup.popup = popup; wl_shell_surface->popup = popup;
} }
static void static void
@ -287,15 +344,18 @@ wl_shell_surface_set_popup (struct wl_client *client,
int32_t y, int32_t y,
uint32_t flags) uint32_t flags)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (wl_resource_get_user_data (resource));
MetaWaylandSurface *surface =
surface_from_wl_shell_surface_resource (resource);
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
if (surface->popup.popup) if (wl_shell_surface->popup)
{ {
surface->popup.parent = NULL; wl_shell_surface->parent_surface = NULL;
meta_wayland_popup_dismiss (surface->popup.popup); meta_wayland_popup_dismiss (wl_shell_surface->popup);
} }
wl_shell_surface_set_state (surface, wl_shell_surface_set_state (surface,
@ -308,10 +368,10 @@ wl_shell_surface_set_popup (struct wl_client *client,
} }
set_wl_shell_surface_parent (surface, parent_surf); set_wl_shell_surface_parent (surface, parent_surf);
surface->wl_shell.popup_seat = seat; wl_shell_surface->popup_seat = seat;
surface->wl_shell.x = x; wl_shell_surface->x = x;
surface->wl_shell.y = y; wl_shell_surface->y = y;
surface->wl_shell.pending_popup = TRUE; wl_shell_surface->pending_popup = TRUE;
if (surface->window && parent_surf->window) if (surface->window && parent_surf->window)
sync_wl_shell_parent_relationship (surface, parent_surf); sync_wl_shell_parent_relationship (surface, parent_surf);
@ -322,7 +382,8 @@ wl_shell_surface_set_maximized (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
struct wl_resource *output) struct wl_resource *output)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface =
surface_from_wl_shell_surface_resource (resource);
wl_shell_surface_set_state (surface, wl_shell_surface_set_state (surface,
META_WL_SHELL_SURFACE_STATE_MAXIMIZED); META_WL_SHELL_SURFACE_STATE_MAXIMIZED);
@ -333,10 +394,13 @@ wl_shell_surface_set_title (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
const char *title) const char *title)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (wl_resource_get_user_data (resource));
MetaWaylandSurface *surface =
surface_from_wl_shell_surface_resource (resource);
g_clear_pointer (&surface->wl_shell.title, g_free); g_clear_pointer (&wl_shell_surface->title, g_free);
surface->wl_shell.title = g_strdup (title); wl_shell_surface->title = g_strdup (title);
if (surface->window) if (surface->window)
meta_window_set_title (surface->window, title); meta_window_set_title (surface->window, title);
@ -347,10 +411,13 @@ wl_shell_surface_set_class (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
const char *class_) const char *class_)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (wl_resource_get_user_data (resource));
MetaWaylandSurface *surface =
surface_from_wl_shell_surface_resource (resource);
g_clear_pointer (&surface->wl_shell.wm_class, g_free); g_clear_pointer (&wl_shell_surface->wm_class, g_free);
surface->wl_shell.wm_class = g_strdup (class_); wl_shell_surface->wm_class = g_strdup (class_);
if (surface->window) if (surface->window)
meta_window_set_wm_class (surface->window, class_, class_); meta_window_set_wm_class (surface->window, class_, class_);
@ -373,44 +440,49 @@ static void
sync_wl_shell_parent_relationship (MetaWaylandSurface *surface, sync_wl_shell_parent_relationship (MetaWaylandSurface *surface,
MetaWaylandSurface *parent) MetaWaylandSurface *parent)
{ {
MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (surface->role);
meta_window_set_transient_for (surface->window, parent->window); meta_window_set_transient_for (surface->window, parent->window);
if (surface->wl_shell.state == META_WL_SHELL_SURFACE_STATE_POPUP || if (wl_shell_surface->state == META_WL_SHELL_SURFACE_STATE_POPUP ||
surface->wl_shell.state == META_WL_SHELL_SURFACE_STATE_TRANSIENT) wl_shell_surface->state == META_WL_SHELL_SURFACE_STATE_TRANSIENT)
meta_window_wayland_place_relative_to (surface->window, meta_window_wayland_place_relative_to (surface->window,
parent->window, parent->window,
surface->wl_shell.x, wl_shell_surface->x,
surface->wl_shell.y); wl_shell_surface->y);
if (surface->wl_shell.state == META_WL_SHELL_SURFACE_STATE_POPUP && if (wl_shell_surface->state == META_WL_SHELL_SURFACE_STATE_POPUP &&
surface->wl_shell.pending_popup) wl_shell_surface->pending_popup)
{ {
create_popup (surface); meta_wayland_wl_shell_surface_create_popup (wl_shell_surface);
surface->wl_shell.pending_popup = FALSE; wl_shell_surface->pending_popup = FALSE;
} }
} }
static void static void
create_wl_shell_surface_window (MetaWaylandSurface *surface) create_wl_shell_surface_window (MetaWaylandSurface *surface)
{ {
MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (surface->role);
MetaWaylandSurface *parent; MetaWaylandSurface *parent;
GList *l; GList *l;
surface->window = meta_window_wayland_new (meta_get_display (), surface); surface->window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, surface->window); meta_wayland_surface_set_window (surface, surface->window);
if (surface->wl_shell.title) if (wl_shell_surface->title)
meta_window_set_title (surface->window, surface->wl_shell.title); meta_window_set_title (surface->window, wl_shell_surface->title);
if (surface->wl_shell.wm_class) if (wl_shell_surface->wm_class)
meta_window_set_wm_class (surface->window, meta_window_set_wm_class (surface->window,
surface->wl_shell.wm_class, wl_shell_surface->wm_class,
surface->wl_shell.wm_class); wl_shell_surface->wm_class);
parent = surface->wl_shell.parent_surface; parent = wl_shell_surface->parent_surface;
if (parent && parent->window) if (parent && parent->window)
sync_wl_shell_parent_relationship (surface, parent); sync_wl_shell_parent_relationship (surface, parent);
for (l = surface->wl_shell.children; l; l = l->next) for (l = wl_shell_surface->children; l; l = l->next)
{ {
MetaWaylandSurface *child = l->data; MetaWaylandSurface *child = l->data;
@ -426,8 +498,10 @@ wl_shell_get_shell_surface (struct wl_client *client,
struct wl_resource *surface_resource) struct wl_resource *surface_resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandWlShellSurface *wl_shell_surface;
if (surface->wl_shell_surface != NULL) if (META_IS_WAYLAND_WL_SHELL_SURFACE (surface->role) &&
META_WAYLAND_WL_SHELL_SURFACE (surface->role)->resource)
{ {
wl_resource_post_error (surface_resource, wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT, WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -444,13 +518,15 @@ wl_shell_get_shell_surface (struct wl_client *client,
return; return;
} }
surface->wl_shell_surface = wl_resource_create (client, wl_shell_surface = META_WAYLAND_WL_SHELL_SURFACE (surface->role);
wl_shell_surface->resource =
wl_resource_create (client,
&wl_shell_surface_interface, &wl_shell_surface_interface,
wl_resource_get_version (resource), wl_resource_get_version (resource),
id); id);
wl_resource_set_implementation (surface->wl_shell_surface, wl_resource_set_implementation (wl_shell_surface->resource,
&meta_wayland_wl_shell_surface_interface, &meta_wayland_wl_shell_surface_interface,
surface, wl_shell_surface,
wl_shell_surface_destructor); wl_shell_surface_destructor);
create_wl_shell_surface_window (surface); create_wl_shell_surface_window (surface);
@ -476,6 +552,8 @@ static void
wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role, wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending) MetaWaylandPendingState *pending)
{ {
MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (surface_role);
MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurfaceRoleClass *surface_role_class;
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
@ -495,8 +573,8 @@ wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
} }
else if (!surface->buffer_ref.buffer && window) else if (!surface->buffer_ref.buffer && window)
{ {
if (surface->popup.popup) if (wl_shell_surface->popup)
meta_wayland_popup_dismiss (surface->popup.popup); meta_wayland_popup_dismiss (wl_shell_surface->popup);
else else
meta_wayland_surface_destroy_window (surface); meta_wayland_surface_destroy_window (surface);
return; return;
@ -518,12 +596,12 @@ wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
static MetaWaylandSurface * static MetaWaylandSurface *
wl_shell_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role) wl_shell_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role)
{ {
MetaWaylandSurface *surface = MetaWaylandWlShellSurface *wl_shell_surface =
meta_wayland_surface_role_get_surface (surface_role); META_WAYLAND_WL_SHELL_SURFACE (surface_role);
if (surface->wl_shell.state == META_WL_SHELL_SURFACE_STATE_POPUP && if (wl_shell_surface->state == META_WL_SHELL_SURFACE_STATE_POPUP &&
surface->popup.parent) wl_shell_surface->parent_surface)
return meta_wayland_surface_get_toplevel (surface->popup.parent); return meta_wayland_surface_get_toplevel (wl_shell_surface->parent_surface);
else else
return meta_wayland_surface_role_get_surface (surface_role); return meta_wayland_surface_role_get_surface (surface_role);
} }
@ -534,15 +612,13 @@ wl_shell_surface_role_configure (MetaWaylandSurfaceRoleShellSurface *shell_surfa
int new_height, int new_height,
MetaWaylandSerial *sent_serial) MetaWaylandSerial *sent_serial)
{ {
MetaWaylandSurfaceRole *surface_role = MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_SURFACE_ROLE (shell_surface_role); META_WAYLAND_WL_SHELL_SURFACE (shell_surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
if (!surface->wl_shell_surface) if (!wl_shell_surface->resource)
return; return;
wl_shell_surface_send_configure (surface->wl_shell_surface, wl_shell_surface_send_configure (wl_shell_surface->resource,
0, 0,
new_width, new_height); new_width, new_height);
} }
@ -551,12 +627,10 @@ static void
wl_shell_surface_role_managed (MetaWaylandSurfaceRoleShellSurface *shell_surface_role, wl_shell_surface_role_managed (MetaWaylandSurfaceRoleShellSurface *shell_surface_role,
MetaWindow *window) MetaWindow *window)
{ {
MetaWaylandSurfaceRole *surface_role = MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_SURFACE_ROLE (shell_surface_role); META_WAYLAND_WL_SHELL_SURFACE (shell_surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
if (surface->wl_shell.state == META_WL_SHELL_SURFACE_STATE_POPUP) if (wl_shell_surface->state == META_WL_SHELL_SURFACE_STATE_POPUP)
meta_window_set_type (window, META_WINDOW_DROPDOWN_MENU); meta_window_set_type (window, META_WINDOW_DROPDOWN_MENU);
} }
@ -564,12 +638,10 @@ static void
wl_shell_surface_role_ping (MetaWaylandSurfaceRoleShellSurface *shell_surface_role, wl_shell_surface_role_ping (MetaWaylandSurfaceRoleShellSurface *shell_surface_role,
guint32 serial) guint32 serial)
{ {
MetaWaylandSurfaceRole *surface_role = MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_SURFACE_ROLE (shell_surface_role); META_WAYLAND_WL_SHELL_SURFACE (shell_surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
wl_shell_surface_send_ping (surface->wl_shell_surface, serial); wl_shell_surface_send_ping (wl_shell_surface->resource, serial);
} }
static void static void
@ -581,23 +653,23 @@ wl_shell_surface_role_close (MetaWaylandSurfaceRoleShellSurface *shell_surface_r
static void static void
meta_wayland_wl_shell_surface_popup_done (MetaWaylandPopupSurface *popup_surface) meta_wayland_wl_shell_surface_popup_done (MetaWaylandPopupSurface *popup_surface)
{ {
MetaWaylandSurfaceRole *surface_role = MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_SURFACE_ROLE (popup_surface); META_WAYLAND_WL_SHELL_SURFACE (popup_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
wl_shell_surface_send_popup_done (surface->wl_shell_surface); wl_shell_surface_send_popup_done (wl_shell_surface->resource);
} }
static void static void
meta_wayland_wl_shell_surface_popup_dismiss (MetaWaylandPopupSurface *popup_surface) meta_wayland_wl_shell_surface_popup_dismiss (MetaWaylandPopupSurface *popup_surface)
{ {
MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (popup_surface);
MetaWaylandSurfaceRole *surface_role = MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (popup_surface); META_WAYLAND_SURFACE_ROLE (popup_surface);
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
surface->popup.popup = NULL; wl_shell_surface->popup = NULL;
meta_wayland_surface_destroy_window (surface); meta_wayland_surface_destroy_window (surface);
} }
@ -619,6 +691,20 @@ popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface)
iface->get_surface = meta_wayland_wl_shell_surface_popup_get_surface; iface->get_surface = meta_wayland_wl_shell_surface_popup_get_surface;
} }
static void
wl_shell_surface_role_finalize (GObject *object)
{
MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (object);
GObjectClass *object_class;
g_clear_pointer (&wl_shell_surface->resource, wl_resource_destroy);
object_class =
G_OBJECT_CLASS (meta_wayland_wl_shell_surface_parent_class);
object_class->finalize (object);
}
static void static void
meta_wayland_wl_shell_surface_init (MetaWaylandWlShellSurface *wl_shell_surface) meta_wayland_wl_shell_surface_init (MetaWaylandWlShellSurface *wl_shell_surface)
{ {
@ -627,9 +713,13 @@ meta_wayland_wl_shell_surface_init (MetaWaylandWlShellSurface *wl_shell_surface)
static void static void
meta_wayland_wl_shell_surface_class_init (MetaWaylandWlShellSurfaceClass *klass) meta_wayland_wl_shell_surface_class_init (MetaWaylandWlShellSurfaceClass *klass)
{ {
GObjectClass *object_class;
MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurfaceRoleClass *surface_role_class;
MetaWaylandSurfaceRoleShellSurfaceClass *shell_surface_role_class; MetaWaylandSurfaceRoleShellSurfaceClass *shell_surface_role_class;
object_class = G_OBJECT_CLASS (klass);
object_class->finalize = wl_shell_surface_role_finalize;
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
surface_role_class->commit = wl_shell_surface_role_commit; surface_role_class->commit = wl_shell_surface_role_commit;
surface_role_class->get_toplevel = wl_shell_surface_role_get_toplevel; surface_role_class->get_toplevel = wl_shell_surface_role_get_toplevel;

View File

@ -39,6 +39,8 @@ struct _MetaWaylandXdgSurface
{ {
MetaWaylandSurfaceRoleShellSurface parent; MetaWaylandSurfaceRoleShellSurface parent;
struct wl_resource *resource;
struct wl_resource *xdg_shell_resource;
MetaWaylandSerial acked_configure_serial; MetaWaylandSerial acked_configure_serial;
gboolean has_set_geometry; gboolean has_set_geometry;
}; };
@ -50,6 +52,14 @@ G_DEFINE_TYPE (MetaWaylandXdgSurface,
struct _MetaWaylandXdgPopup struct _MetaWaylandXdgPopup
{ {
MetaWaylandSurfaceRoleShellSurface parent; MetaWaylandSurfaceRoleShellSurface parent;
struct wl_resource *resource;
struct wl_resource *xdg_shell_resource;
MetaWaylandSurface *parent_surface;
struct wl_listener parent_destroy_listener;
MetaWaylandPopup *popup;
}; };
static void static void
@ -61,6 +71,26 @@ G_DEFINE_TYPE_WITH_CODE (MetaWaylandXdgPopup,
G_IMPLEMENT_INTERFACE (META_TYPE_WAYLAND_POPUP_SURFACE, G_IMPLEMENT_INTERFACE (META_TYPE_WAYLAND_POPUP_SURFACE,
popup_surface_iface_init)); popup_surface_iface_init));
static MetaWaylandSurface *
surface_from_xdg_surface_resource (struct wl_resource *resource)
{
MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (xdg_surface);
return meta_wayland_surface_role_get_surface (surface_role);
}
static MetaWaylandSurface *
surface_from_xdg_popup_resource (struct wl_resource *resource)
{
MetaWaylandXdgPopup *xdg_popup = wl_resource_get_user_data (resource);
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (xdg_popup);
return meta_wayland_surface_role_get_surface (surface_role);
}
static void static void
xdg_shell_destroy (struct wl_client *client, xdg_shell_destroy (struct wl_client *client,
struct wl_resource *resource) struct wl_resource *resource)
@ -91,12 +121,13 @@ xdg_shell_pong (struct wl_client *client,
static void static void
xdg_surface_destructor (struct wl_resource *resource) xdg_surface_destructor (struct wl_resource *resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (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, meta_wayland_compositor_destroy_frame_callbacks (surface->compositor,
surface); surface);
meta_wayland_surface_destroy_window (surface); meta_wayland_surface_destroy_window (surface);
surface->xdg_surface = NULL; xdg_surface->resource = NULL;
} }
static void static void
@ -111,13 +142,14 @@ xdg_surface_set_parent (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
struct wl_resource *parent_resource) struct wl_resource *parent_resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
MetaWindow *transient_for = NULL; MetaWindow *transient_for = NULL;
if (parent_resource) if (parent_resource)
{ {
MetaWaylandSurface *parent_surface = MetaWaylandSurface *parent_surface =
wl_resource_get_user_data (parent_resource); surface_from_xdg_surface_resource (parent_resource);
transient_for = parent_surface->window; transient_for = parent_surface->window;
} }
@ -129,7 +161,7 @@ xdg_surface_set_title (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
const char *title) const char *title)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
meta_window_set_title (surface->window, title); meta_window_set_title (surface->window, title);
} }
@ -139,7 +171,7 @@ xdg_surface_set_app_id (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
const char *app_id) const char *app_id)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
meta_window_set_wm_class (surface->window, app_id, app_id); meta_window_set_wm_class (surface->window, app_id, app_id);
} }
@ -153,7 +185,7 @@ xdg_surface_show_window_menu (struct wl_client *client,
int32_t y) int32_t y)
{ {
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, FALSE, NULL, NULL)) if (!meta_wayland_seat_get_grab_info (seat, surface, serial, FALSE, NULL, NULL))
return; return;
@ -170,7 +202,7 @@ xdg_surface_move (struct wl_client *client,
guint32 serial) guint32 serial)
{ {
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
gfloat x, y; gfloat x, y;
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y)) if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y))
@ -210,7 +242,7 @@ xdg_surface_resize (struct wl_client *client,
guint32 edges) guint32 edges)
{ {
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
gfloat x, y; gfloat x, y;
MetaGrabOp grab_op; MetaGrabOp grab_op;
@ -226,8 +258,7 @@ xdg_surface_ack_configure (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
uint32_t serial) uint32_t serial)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface->role);
xdg_surface->acked_configure_serial.set = TRUE; xdg_surface->acked_configure_serial.set = TRUE;
xdg_surface->acked_configure_serial.value = serial; xdg_surface->acked_configure_serial.value = serial;
@ -241,7 +272,7 @@ xdg_surface_set_window_geometry (struct wl_client *client,
int32_t width, int32_t width,
int32_t height) int32_t height)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
surface->pending->has_new_geometry = TRUE; surface->pending->has_new_geometry = TRUE;
surface->pending->new_geometry.x = x; surface->pending->new_geometry.x = x;
@ -254,7 +285,7 @@ static void
xdg_surface_set_maximized (struct wl_client *client, xdg_surface_set_maximized (struct wl_client *client,
struct wl_resource *resource) struct wl_resource *resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
meta_window_maximize (surface->window, META_MAXIMIZE_BOTH); meta_window_maximize (surface->window, META_MAXIMIZE_BOTH);
} }
@ -263,7 +294,7 @@ static void
xdg_surface_unset_maximized (struct wl_client *client, xdg_surface_unset_maximized (struct wl_client *client,
struct wl_resource *resource) struct wl_resource *resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH); meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH);
} }
@ -273,7 +304,7 @@ xdg_surface_set_fullscreen (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
struct wl_resource *output_resource) struct wl_resource *output_resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
meta_window_make_fullscreen (surface->window); meta_window_make_fullscreen (surface->window);
} }
@ -282,7 +313,7 @@ static void
xdg_surface_unset_fullscreen (struct wl_client *client, xdg_surface_unset_fullscreen (struct wl_client *client,
struct wl_resource *resource) struct wl_resource *resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
meta_window_unmake_fullscreen (surface->window); meta_window_unmake_fullscreen (surface->window);
} }
@ -291,7 +322,7 @@ static void
xdg_surface_set_minimized (struct wl_client *client, xdg_surface_set_minimized (struct wl_client *client,
struct wl_resource *resource) struct wl_resource *resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
meta_window_minimize (surface->window); meta_window_minimize (surface->window);
} }
@ -320,9 +351,11 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
struct wl_resource *surface_resource) struct wl_resource *surface_resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandXdgSurface *xdg_surface;
MetaWindow *window; MetaWindow *window;
if (surface->xdg_surface != NULL) if (META_IS_WAYLAND_XDG_SURFACE (surface->role) &&
META_WAYLAND_XDG_SURFACE (surface->role)->resource)
{ {
wl_resource_post_error (surface_resource, wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT, WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -338,16 +371,17 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
return; return;
} }
surface->xdg_surface = wl_resource_create (client, xdg_surface = META_WAYLAND_XDG_SURFACE (surface->role);
xdg_surface->resource = wl_resource_create (client,
&xdg_surface_interface, &xdg_surface_interface,
wl_resource_get_version (resource), wl_resource_get_version (resource),
id); id);
wl_resource_set_implementation (surface->xdg_surface, wl_resource_set_implementation (xdg_surface->resource,
&meta_wayland_xdg_surface_interface, &meta_wayland_xdg_surface_interface,
surface, xdg_surface,
xdg_surface_destructor); xdg_surface_destructor);
surface->xdg_shell_resource = resource; xdg_surface->xdg_shell_resource = resource;
window = meta_window_wayland_new (meta_get_display (), surface); window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, window); meta_wayland_surface_set_window (surface, window);
@ -356,20 +390,22 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
static void static void
xdg_popup_destructor (struct wl_resource *resource) xdg_popup_destructor (struct wl_resource *resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = surface_from_xdg_popup_resource (resource);
MetaWaylandXdgPopup *xdg_popup =
META_WAYLAND_XDG_POPUP (wl_resource_get_user_data (resource));
meta_wayland_compositor_destroy_frame_callbacks (surface->compositor, meta_wayland_compositor_destroy_frame_callbacks (surface->compositor,
surface); surface);
if (surface->popup.parent) if (xdg_popup->parent_surface)
{ {
wl_list_remove (&surface->popup.parent_destroy_listener.link); wl_list_remove (&xdg_popup->parent_destroy_listener.link);
surface->popup.parent = NULL; xdg_popup->parent_surface = NULL;
} }
if (surface->popup.popup) if (xdg_popup->popup)
meta_wayland_popup_dismiss (surface->popup.popup); meta_wayland_popup_dismiss (xdg_popup->popup);
surface->xdg_popup = NULL; xdg_popup->resource = NULL;
} }
static void static void
@ -387,13 +423,17 @@ static void
handle_popup_parent_destroyed (struct wl_listener *listener, handle_popup_parent_destroyed (struct wl_listener *listener,
void *data) 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 = MetaWaylandSurface *surface =
wl_container_of (listener, surface, popup.parent_destroy_listener); meta_wayland_surface_role_get_surface (surface_role);
wl_resource_post_error (surface->xdg_shell_resource, wl_resource_post_error (xdg_popup->xdg_shell_resource,
XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP, XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
"destroyed popup not top most popup"); "destroyed popup not top most popup");
surface->popup.parent = NULL; xdg_popup->parent_surface = NULL;
meta_wayland_surface_destroy_window (surface); meta_wayland_surface_destroy_window (surface);
} }
@ -409,7 +449,6 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
int32_t x, int32_t x,
int32_t y) int32_t y)
{ {
struct wl_resource *popup_resource;
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandPopupSurface *popup_surface; MetaWaylandPopupSurface *popup_surface;
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
@ -417,9 +456,11 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWindow *window; MetaWindow *window;
MetaDisplay *display = meta_get_display (); MetaDisplay *display = meta_get_display ();
MetaWaylandXdgPopup *xdg_popup;
MetaWaylandPopup *popup; MetaWaylandPopup *popup;
if (surface->xdg_popup != NULL) if (META_IS_WAYLAND_XDG_POPUP (surface->role) &&
META_WAYLAND_XDG_POPUP (surface->role)->resource)
{ {
wl_resource_post_error (surface_resource, wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT, WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -437,7 +478,8 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
if (parent_surf == NULL || if (parent_surf == NULL ||
parent_surf->window == NULL || parent_surf->window == NULL ||
(parent_surf->xdg_popup == NULL && parent_surf->xdg_surface == NULL)) (!META_IS_WAYLAND_XDG_POPUP (parent_surf->role) &&
!META_IS_WAYLAND_XDG_SURFACE (parent_surf->role)))
{ {
wl_resource_post_error (resource, wl_resource_post_error (resource,
XDG_SHELL_ERROR_INVALID_POPUP_PARENT, XDG_SHELL_ERROR_INVALID_POPUP_PARENT,
@ -446,7 +488,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
} }
top_popup = meta_wayland_pointer_get_top_popup (&seat->pointer); top_popup = meta_wayland_pointer_get_top_popup (&seat->pointer);
if ((top_popup == NULL && parent_surf->xdg_surface == NULL) || if ((top_popup == NULL && !META_IS_WAYLAND_XDG_SURFACE (parent_surf->role)) ||
(top_popup != NULL && parent_surf != top_popup)) (top_popup != NULL && parent_surf != top_popup))
{ {
wl_resource_post_error (resource, wl_resource_post_error (resource,
@ -455,26 +497,26 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
return; return;
} }
popup_resource = wl_resource_create (client, &xdg_popup_interface, 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_get_version (resource), id);
wl_resource_set_implementation (popup_resource, wl_resource_set_implementation (xdg_popup->resource,
&meta_wayland_xdg_popup_interface, &meta_wayland_xdg_popup_interface,
surface, xdg_popup,
xdg_popup_destructor); xdg_popup_destructor);
surface->xdg_popup = popup_resource; xdg_popup->xdg_shell_resource = resource;
surface->xdg_shell_resource = resource;
if (!meta_wayland_seat_can_popup (seat, serial)) if (!meta_wayland_seat_can_popup (seat, serial))
{ {
xdg_popup_send_popup_done (popup_resource); xdg_popup_send_popup_done (xdg_popup->resource);
return; return;
} }
surface->popup.parent = parent_surf; xdg_popup->parent_surface = parent_surf;
surface->popup.parent_destroy_listener.notify = handle_popup_parent_destroyed; xdg_popup->parent_destroy_listener.notify = handle_popup_parent_destroyed;
wl_resource_add_destroy_listener (parent_surf->resource, wl_resource_add_destroy_listener (parent_surf->resource,
&surface->popup.parent_destroy_listener); &xdg_popup->parent_destroy_listener);
window = meta_window_wayland_new (display, surface); window = meta_window_wayland_new (display, surface);
meta_window_wayland_place_relative_to (window, parent_surf->window, x, y); meta_window_wayland_place_relative_to (window, parent_surf->window, x, y);
@ -488,12 +530,12 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
popup_surface); popup_surface);
if (popup == NULL) if (popup == NULL)
{ {
xdg_popup_send_popup_done (surface->xdg_popup); xdg_popup_send_popup_done (xdg_popup->resource);
meta_wayland_surface_destroy_window (surface); meta_wayland_surface_destroy_window (surface);
return; return;
} }
surface->popup.popup = popup; xdg_popup->popup = popup;
} }
static const struct xdg_shell_interface meta_wayland_xdg_shell_interface = { static const struct xdg_shell_interface meta_wayland_xdg_shell_interface = {
@ -631,22 +673,24 @@ xdg_surface_role_configure (MetaWaylandSurfaceRoleShellSurface *shell_surface_ro
int new_height, int new_height,
MetaWaylandSerial *sent_serial) MetaWaylandSerial *sent_serial)
{ {
MetaWaylandXdgSurface *xdg_surface =
META_WAYLAND_XDG_SURFACE (shell_surface_role);
MetaWaylandSurfaceRole *surface_role = MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (shell_surface_role); META_WAYLAND_SURFACE_ROLE (shell_surface_role);
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
struct wl_client *client = wl_resource_get_client (surface->xdg_surface); struct wl_client *client = wl_resource_get_client (xdg_surface->resource);
struct wl_display *display = wl_client_get_display (client); struct wl_display *display = wl_client_get_display (client);
uint32_t serial = wl_display_next_serial (display); uint32_t serial = wl_display_next_serial (display);
struct wl_array states; struct wl_array states;
if (!surface->xdg_surface) if (!xdg_surface->resource)
return; return;
wl_array_init (&states); wl_array_init (&states);
fill_states (&states, surface->window); fill_states (&states, surface->window);
xdg_surface_send_configure (surface->xdg_surface, xdg_surface_send_configure (xdg_surface->resource,
new_width, new_height, new_width, new_height,
&states, &states,
serial); serial);
@ -670,23 +714,29 @@ static void
xdg_surface_role_ping (MetaWaylandSurfaceRoleShellSurface *shell_surface_role, xdg_surface_role_ping (MetaWaylandSurfaceRoleShellSurface *shell_surface_role,
uint32_t serial) uint32_t serial)
{ {
MetaWaylandSurfaceRole *surface_role = MetaWaylandXdgSurface *xdg_surface =
META_WAYLAND_SURFACE_ROLE (shell_surface_role); META_WAYLAND_XDG_SURFACE (shell_surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
xdg_shell_send_ping (surface->xdg_shell_resource, serial); xdg_shell_send_ping (xdg_surface->xdg_shell_resource, serial);
} }
static void static void
xdg_surface_role_close (MetaWaylandSurfaceRoleShellSurface *shell_surface_role) xdg_surface_role_close (MetaWaylandSurfaceRoleShellSurface *shell_surface_role)
{ {
MetaWaylandSurfaceRole *surface_role = MetaWaylandXdgSurface *xdg_surface =
META_WAYLAND_SURFACE_ROLE (shell_surface_role); META_WAYLAND_XDG_SURFACE (shell_surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
xdg_surface_send_close (surface->xdg_surface); xdg_surface_send_close (xdg_surface->resource);
}
static void
xdg_surface_role_finalize (GObject *object)
{
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (object);
g_clear_pointer (&xdg_surface->resource, wl_resource_destroy);
G_OBJECT_CLASS (meta_wayland_xdg_surface_parent_class)->finalize (object);
} }
static void static void
@ -697,15 +747,19 @@ meta_wayland_xdg_surface_init (MetaWaylandXdgSurface *role)
static void static void
meta_wayland_xdg_surface_class_init (MetaWaylandXdgSurfaceClass *klass) meta_wayland_xdg_surface_class_init (MetaWaylandXdgSurfaceClass *klass)
{ {
MetaWaylandSurfaceRoleClass *surface_role_class = GObjectClass *object_class;
META_WAYLAND_SURFACE_ROLE_CLASS (klass); MetaWaylandSurfaceRoleClass *surface_role_class;
MetaWaylandSurfaceRoleShellSurfaceClass *shell_surface_role_class;
object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xdg_surface_role_finalize;
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
surface_role_class->commit = xdg_surface_role_commit; surface_role_class->commit = xdg_surface_role_commit;
surface_role_class->get_toplevel = xdg_surface_role_get_toplevel; surface_role_class->get_toplevel = xdg_surface_role_get_toplevel;
MetaWaylandSurfaceRoleShellSurfaceClass *shell_surface_role_class = shell_surface_role_class =
META_WAYLAND_SURFACE_ROLE_SHELL_SURFACE_CLASS (klass); META_WAYLAND_SURFACE_ROLE_SHELL_SURFACE_CLASS (klass);
shell_surface_role_class->configure = xdg_surface_role_configure; shell_surface_role_class->configure = xdg_surface_role_configure;
shell_surface_role_class->managed = xdg_surface_role_managed; shell_surface_role_class->managed = xdg_surface_role_managed;
shell_surface_role_class->ping = xdg_surface_role_ping; shell_surface_role_class->ping = xdg_surface_role_ping;
@ -752,10 +806,9 @@ xdg_popup_role_commit (MetaWaylandSurfaceRole *surface_role,
static MetaWaylandSurface * static MetaWaylandSurface *
xdg_popup_role_get_toplevel (MetaWaylandSurfaceRole *surface_role) xdg_popup_role_get_toplevel (MetaWaylandSurfaceRole *surface_role)
{ {
MetaWaylandSurface *surface = MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (surface_role);
meta_wayland_surface_role_get_surface (surface_role);
return meta_wayland_surface_get_toplevel (surface->popup.parent); return meta_wayland_surface_get_toplevel (xdg_popup->parent_surface);
} }
static void static void
@ -772,11 +825,8 @@ static void
xdg_popup_role_managed (MetaWaylandSurfaceRoleShellSurface *shell_surface_role, xdg_popup_role_managed (MetaWaylandSurfaceRoleShellSurface *shell_surface_role,
MetaWindow *window) MetaWindow *window)
{ {
MetaWaylandSurfaceRole *surface_role = MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (shell_surface_role);
META_WAYLAND_SURFACE_ROLE (shell_surface_role); MetaWaylandSurface *parent = xdg_popup->parent_surface;
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandSurface *parent = surface->popup.parent;
g_assert (parent); g_assert (parent);
@ -788,23 +838,17 @@ static void
xdg_popup_role_ping (MetaWaylandSurfaceRoleShellSurface *shell_surface_role, xdg_popup_role_ping (MetaWaylandSurfaceRoleShellSurface *shell_surface_role,
uint32_t serial) uint32_t serial)
{ {
MetaWaylandSurfaceRole *surface_role = MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (shell_surface_role);
META_WAYLAND_SURFACE_ROLE (shell_surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
xdg_shell_send_ping (surface->xdg_shell_resource, serial); xdg_shell_send_ping (xdg_popup->xdg_shell_resource, serial);
} }
static void static void
meta_wayland_xdg_popup_done (MetaWaylandPopupSurface *popup_surface) meta_wayland_xdg_popup_done (MetaWaylandPopupSurface *popup_surface)
{ {
MetaWaylandSurfaceRole *surface_role = MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (popup_surface);
META_WAYLAND_SURFACE_ROLE (popup_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
xdg_popup_send_popup_done (surface->xdg_popup); xdg_popup_send_popup_done (xdg_popup->resource);
} }
static void static void
@ -816,15 +860,15 @@ meta_wayland_xdg_popup_dismiss (MetaWaylandPopupSurface *popup_surface)
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandSurface *top_popup; MetaWaylandSurface *top_popup;
top_popup = meta_wayland_popup_get_top_popup (surface->popup.popup); top_popup = meta_wayland_popup_get_top_popup (xdg_popup->popup);
if (surface != top_popup) if (surface != top_popup)
{ {
wl_resource_post_error (surface->xdg_shell_resource, wl_resource_post_error (xdg_popup->xdg_shell_resource,
XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP, XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
"destroyed popup not top most popup"); "destroyed popup not top most popup");
} }
surface->popup.popup = NULL; xdg_popup->popup = NULL;
meta_wayland_surface_destroy_window (surface); meta_wayland_surface_destroy_window (surface);
} }
@ -846,6 +890,16 @@ popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface)
iface->get_surface = meta_wayland_xdg_popup_get_surface; iface->get_surface = meta_wayland_xdg_popup_get_surface;
} }
static void
xdg_popup_role_finalize (GObject *object)
{
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (object);
g_clear_pointer (&xdg_popup->resource, wl_resource_destroy);
G_OBJECT_CLASS (meta_wayland_xdg_popup_parent_class)->finalize (object);
}
static void static void
meta_wayland_xdg_popup_init (MetaWaylandXdgPopup *role) meta_wayland_xdg_popup_init (MetaWaylandXdgPopup *role)
{ {
@ -854,15 +908,19 @@ meta_wayland_xdg_popup_init (MetaWaylandXdgPopup *role)
static void static void
meta_wayland_xdg_popup_class_init (MetaWaylandXdgPopupClass *klass) meta_wayland_xdg_popup_class_init (MetaWaylandXdgPopupClass *klass)
{ {
MetaWaylandSurfaceRoleClass *surface_role_class = GObjectClass *object_class;
META_WAYLAND_SURFACE_ROLE_CLASS (klass); MetaWaylandSurfaceRoleClass *surface_role_class;
MetaWaylandSurfaceRoleShellSurfaceClass *shell_surface_role_class;
object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xdg_popup_role_finalize;
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
surface_role_class->commit = xdg_popup_role_commit; surface_role_class->commit = xdg_popup_role_commit;
surface_role_class->get_toplevel = xdg_popup_role_get_toplevel; surface_role_class->get_toplevel = xdg_popup_role_get_toplevel;
MetaWaylandSurfaceRoleShellSurfaceClass *shell_surface_role_class = shell_surface_role_class =
META_WAYLAND_SURFACE_ROLE_SHELL_SURFACE_CLASS (klass); META_WAYLAND_SURFACE_ROLE_SHELL_SURFACE_CLASS (klass);
shell_surface_role_class->configure = xdg_popup_role_configure; shell_surface_role_class->configure = xdg_popup_role_configure;
shell_surface_role_class->managed = xdg_popup_role_managed; shell_surface_role_class->managed = xdg_popup_role_managed;
shell_surface_role_class->ping = xdg_popup_role_ping; shell_surface_role_class->ping = xdg_popup_role_ping;