[mutter] wayland: Add 'MetaWaylandPopupSurface' bridge between popup and surface



commit 229a143eac5e16c3a0962c58fbb8878b91bafecc
Author: Jonas Ådahl <jadahl gmail com>
Date:   Thu Jan 21 17:01:08 2016 +0800

    wayland: Add 'MetaWaylandPopupSurface' bridge between popup and surface
    
    Add a bridge between the MetaWaylandPopup object and the corresponding
    popup surface role. This bridge replaces communicating dismissed and
    unmapped popup events.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=763431

 src/wayland/meta-wayland-pointer.c   |    8 ++--
 src/wayland/meta-wayland-pointer.h   |    4 +-
 src/wayland/meta-wayland-popup.c     |   62 ++++++++++++++++--------
 src/wayland/meta-wayland-popup.h     |   24 +++++++--
 src/wayland/meta-wayland-surface.c   |   21 --------
 src/wayland/meta-wayland-surface.h   |    4 --
 src/wayland/meta-wayland-types.h     |    1 +
 src/wayland/meta-wayland-wl-shell.c  |   65 ++++++++++++++++++--------
 src/wayland/meta-wayland-xdg-shell.c |   85 +++++++++++++++++++++-------------
 9 files changed, 164 insertions(+), 110 deletions(-)
---
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 6ae5754..798583b 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -889,8 +889,8 @@ meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
 }
 
 MetaWaylandPopup *
-meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
-                                      MetaWaylandSurface *surface)
+meta_wayland_pointer_start_popup_grab (MetaWaylandPointer      *pointer,
+                                       MetaWaylandPopupSurface *popup_surface)
 {
   MetaWaylandPopupGrab *grab;
 
@@ -899,11 +899,11 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
     return NULL;
 
   if (pointer->grab == &pointer->default_grab)
-    grab = meta_wayland_popup_grab_create (pointer, surface);
+    grab = meta_wayland_popup_grab_create (pointer, popup_surface);
   else
     grab = (MetaWaylandPopupGrab*)pointer->grab;
 
-  return meta_wayland_popup_create (surface, grab);
+  return meta_wayland_popup_create (popup_surface, grab);
 }
 
 void
diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h
index c016bc1..4e97ec9 100644
--- a/src/wayland/meta-wayland-pointer.h
+++ b/src/wayland/meta-wayland-pointer.h
@@ -117,8 +117,8 @@ void meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
 
 void meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer);
 
-MetaWaylandPopup *meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
-                                                         MetaWaylandSurface *popup);
+MetaWaylandPopup *meta_wayland_pointer_start_popup_grab (MetaWaylandPointer      *pointer,
+                                                         MetaWaylandPopupSurface *popup_surface);
 
 void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer);
 
diff --git a/src/wayland/meta-wayland-popup.c b/src/wayland/meta-wayland-popup.c
index 174a6d8..93fea93 100644
--- a/src/wayland/meta-wayland-popup.c
+++ b/src/wayland/meta-wayland-popup.c
@@ -48,6 +48,9 @@
 #include "meta-wayland-private.h"
 #include "meta-wayland-surface.h"
 
+G_DEFINE_INTERFACE (MetaWaylandPopupSurface, meta_wayland_popup_surface,
+                    G_TYPE_OBJECT);
+
 struct _MetaWaylandPopupGrab
 {
   MetaWaylandPointerGrab  generic;
@@ -59,11 +62,9 @@ struct _MetaWaylandPopupGrab
 struct _MetaWaylandPopup
 {
   MetaWaylandPopupGrab *grab;
-  MetaWaylandSurface   *surface;
-  struct wl_listener    surface_destroy_listener;
-  struct wl_signal      destroy_signal;
-
-  struct wl_list        link;
+  struct wl_listener surface_destroy_listener;
+  MetaWaylandPopupSurface *popup_surface;
+  struct wl_list link;
 };
 
 static void
@@ -74,6 +75,29 @@ static void
 meta_wayland_popup_grab_end (MetaWaylandPopupGrab *grab);
 
 static void
+meta_wayland_popup_surface_default_init (MetaWaylandPopupSurfaceInterface *iface)
+{
+}
+
+static void
+meta_wayland_popup_surface_done (MetaWaylandPopupSurface *popup_surface)
+{
+  META_WAYLAND_POPUP_SURFACE_GET_IFACE (popup_surface)->done (popup_surface);
+}
+
+static void
+meta_wayland_popup_surface_dismiss (MetaWaylandPopupSurface *popup_surface)
+{
+  META_WAYLAND_POPUP_SURFACE_GET_IFACE (popup_surface)->dismiss (popup_surface);
+}
+
+static MetaWaylandSurface *
+meta_wayland_popup_surface_get_surface (MetaWaylandPopupSurface *popup_surface)
+{
+  return META_WAYLAND_POPUP_SURFACE_GET_IFACE (popup_surface)->get_surface (popup_surface);
+}
+
+static void
 popup_grab_focus (MetaWaylandPointerGrab *grab,
                  MetaWaylandSurface     *surface)
 {
@@ -115,9 +139,11 @@ static MetaWaylandPointerGrabInterface popup_grab_interface = {
 };
 
 MetaWaylandPopupGrab *
-meta_wayland_popup_grab_create (MetaWaylandPointer *pointer,
-                                MetaWaylandSurface *surface)
+meta_wayland_popup_grab_create (MetaWaylandPointer      *pointer,
+                                MetaWaylandPopupSurface *popup_surface)
 {
+  MetaWaylandSurface *surface =
+    meta_wayland_popup_surface_get_surface (popup_surface);
   struct wl_client *client = wl_resource_get_client (surface->resource);
   MetaWaylandPopupGrab *grab;
 
@@ -170,7 +196,7 @@ meta_wayland_popup_grab_end (MetaWaylandPopupGrab *grab)
 
   wl_list_for_each_safe (popup, tmp, &grab->all_popups, link)
     {
-      meta_wayland_surface_popup_done (popup->surface);
+      meta_wayland_popup_surface_done (popup->popup_surface);
       meta_wayland_popup_destroy (popup);
     }
 
@@ -191,7 +217,7 @@ meta_wayland_popup_grab_get_top_popup (MetaWaylandPopupGrab *grab)
   g_assert (!wl_list_empty (&grab->all_popups));
   popup = wl_container_of (grab->all_popups.next, popup, link);
 
-  return popup->surface;
+  return meta_wayland_popup_surface_get_surface (popup->popup_surface);
 }
 
 gboolean
@@ -203,7 +229,7 @@ meta_wayland_pointer_grab_is_popup_grab (MetaWaylandPointerGrab *grab)
 void
 meta_wayland_popup_destroy (MetaWaylandPopup *popup)
 {
-  wl_signal_emit (&popup->destroy_signal, popup);
+  meta_wayland_popup_surface_dismiss (popup->popup_surface);
 
   wl_list_remove (&popup->surface_destroy_listener.link);
   wl_list_remove (&popup->link);
@@ -227,12 +253,6 @@ meta_wayland_popup_get_top_popup (MetaWaylandPopup *popup)
   return meta_wayland_popup_grab_get_top_popup (popup->grab);
 }
 
-struct wl_signal *
-meta_wayland_popup_get_destroy_signal (MetaWaylandPopup *popup)
-{
-  return &popup->destroy_signal;
-}
-
 static void
 on_popup_surface_destroy (struct wl_listener *listener,
                          void               *data)
@@ -244,9 +264,11 @@ on_popup_surface_destroy (struct wl_listener *listener,
 }
 
 MetaWaylandPopup *
-meta_wayland_popup_create (MetaWaylandSurface   *surface,
-                           MetaWaylandPopupGrab *grab)
+meta_wayland_popup_create (MetaWaylandPopupSurface *popup_surface,
+                           MetaWaylandPopupGrab    *grab)
 {
+  MetaWaylandSurface *surface =
+    meta_wayland_popup_surface_get_surface (popup_surface);
   MetaWaylandPopup *popup;
 
   /* Don't allow creating popups if the grab has a different client. */
@@ -255,10 +277,8 @@ meta_wayland_popup_create (MetaWaylandSurface   *surface,
 
   popup = g_slice_new0 (MetaWaylandPopup);
   popup->grab = grab;
-  popup->surface = surface;
+  popup->popup_surface = popup_surface;
   popup->surface_destroy_listener.notify = on_popup_surface_destroy;
-  wl_signal_init (&popup->destroy_signal);
-
   if (surface->xdg_popup)
     {
       wl_resource_add_destroy_listener (surface->xdg_popup,
diff --git a/src/wayland/meta-wayland-popup.h b/src/wayland/meta-wayland-popup.h
index 7e4a3a3..eab3a9b 100644
--- a/src/wayland/meta-wayland-popup.h
+++ b/src/wayland/meta-wayland-popup.h
@@ -27,8 +27,22 @@
 #include "meta-wayland-types.h"
 #include "meta-wayland-pointer.h"
 
-MetaWaylandPopupGrab *meta_wayland_popup_grab_create (MetaWaylandPointer *pointer,
-                                                      MetaWaylandSurface *surface);
+#define META_TYPE_WAYLAND_POPUP_SURFACE (meta_wayland_popup_surface_get_type ())
+G_DECLARE_INTERFACE (MetaWaylandPopupSurface, meta_wayland_popup_surface,
+                     META, WAYLAND_POPUP_SURFACE,
+                     GObject);
+
+struct _MetaWaylandPopupSurfaceInterface
+{
+  GTypeInterface parent_iface;
+
+  void (*done) (MetaWaylandPopupSurface *popup_surface);
+  void (*dismiss) (MetaWaylandPopupSurface *popup_surface);
+  MetaWaylandSurface *(*get_surface) (MetaWaylandPopupSurface *popup_surface);
+};
+
+MetaWaylandPopupGrab *meta_wayland_popup_grab_create (MetaWaylandPointer      *pointer,
+                                                      MetaWaylandPopupSurface *popup_surface);
 
 void meta_wayland_popup_grab_destroy (MetaWaylandPopupGrab *grab);
 
@@ -36,8 +50,8 @@ MetaWaylandSurface *meta_wayland_popup_grab_get_top_popup (MetaWaylandPopupGrab
 
 gboolean meta_wayland_pointer_grab_is_popup_grab (MetaWaylandPointerGrab *grab);
 
-MetaWaylandPopup *meta_wayland_popup_create (MetaWaylandSurface   *surface,
-                                             MetaWaylandPopupGrab *grab);
+MetaWaylandPopup *meta_wayland_popup_create (MetaWaylandPopupSurface *surface,
+                                             MetaWaylandPopupGrab    *grab);
 
 void meta_wayland_popup_destroy (MetaWaylandPopup *popup);
 
@@ -45,6 +59,4 @@ void meta_wayland_popup_dismiss (MetaWaylandPopup *popup);
 
 MetaWaylandSurface *meta_wayland_popup_get_top_popup (MetaWaylandPopup *popup);
 
-struct wl_signal *meta_wayland_popup_get_destroy_signal (MetaWaylandPopup *popup);
-
 #endif /* META_WAYLAND_POPUP_H */
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index b66dd94..c86d72f 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -150,9 +150,6 @@ static void
 meta_wayland_surface_role_shell_surface_close (MetaWaylandSurfaceRoleShellSurface *shell_surface_role);
 
 static void
-meta_wayland_surface_role_shell_surface_popup_done (MetaWaylandSurfaceRoleShellSurface *shell_surface_role);
-
-static void
 meta_wayland_surface_role_shell_surface_managed (MetaWaylandSurfaceRoleShellSurface *shell_surface_role,
                                                  MetaWindow                         *window);
 
@@ -1691,15 +1688,6 @@ meta_wayland_surface_delete (MetaWaylandSurface *surface)
 }
 
 void
-meta_wayland_surface_popup_done (MetaWaylandSurface *surface)
-{
-  MetaWaylandSurfaceRoleShellSurface *shell_surface_role =
-    META_WAYLAND_SURFACE_ROLE_SHELL_SURFACE (surface->role);
-
-  meta_wayland_surface_role_shell_surface_popup_done (shell_surface_role);
-}
-
-void
 meta_wayland_surface_window_managed (MetaWaylandSurface *surface,
                                      MetaWindow         *window)
 {
@@ -1928,15 +1916,6 @@ meta_wayland_surface_role_shell_surface_close (MetaWaylandSurfaceRoleShellSurfac
 }
 
 static void
-meta_wayland_surface_role_shell_surface_popup_done (MetaWaylandSurfaceRoleShellSurface *shell_surface_role)
-{
-  MetaWaylandSurfaceRoleShellSurfaceClass *shell_surface_role_class =
-    META_WAYLAND_SURFACE_ROLE_SHELL_SURFACE_GET_CLASS (shell_surface_role);
-
-  shell_surface_role_class->popup_done (shell_surface_role);
-}
-
-static void
 meta_wayland_surface_role_shell_surface_managed (MetaWaylandSurfaceRoleShellSurface *shell_surface_role,
                                                  MetaWindow                         *window)
 {
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 9ac4659..8a00023 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -100,7 +100,6 @@ struct _MetaWaylandSurfaceRoleShellSurfaceClass
   void (*ping) (MetaWaylandSurfaceRoleShellSurface *shell_surface_role,
                 uint32_t                            serial);
   void (*close) (MetaWaylandSurfaceRoleShellSurface *shell_surface_role);
-  void (*popup_done) (MetaWaylandSurfaceRoleShellSurface *shell_surface_role);
 };
 
 #define META_TYPE_WAYLAND_SURFACE_ROLE_SUBSURFACE (meta_wayland_surface_role_subsurface_get_type ())
@@ -231,7 +230,6 @@ struct _MetaWaylandSurface
     struct wl_listener parent_destroy_listener;
 
     MetaWaylandPopup *popup;
-    struct wl_listener destroy_listener;
   } popup;
 
   /* wl_shell_surface */
@@ -305,8 +303,6 @@ void                meta_wayland_surface_ping (MetaWaylandSurface *surface,
                                                guint32             serial);
 void                meta_wayland_surface_delete (MetaWaylandSurface *surface);
 
-void                meta_wayland_surface_popup_done (MetaWaylandSurface *surface);
-
 /* Drag dest functions */
 void                meta_wayland_surface_drag_dest_focus_in  (MetaWaylandSurface   *surface,
                                                               MetaWaylandDataOffer *offer);
diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h
index bea5e20..b07001c 100644
--- a/src/wayland/meta-wayland-types.h
+++ b/src/wayland/meta-wayland-types.h
@@ -28,6 +28,7 @@ typedef struct _MetaWaylandPointerGrab MetaWaylandPointerGrab;
 typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface;
 typedef struct _MetaWaylandPopupGrab MetaWaylandPopupGrab;
 typedef struct _MetaWaylandPopup MetaWaylandPopup;
+typedef struct _MetaWaylandPopupSurface MetaWaylandPopupSurface;
 typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
 typedef struct _MetaWaylandKeyboardGrab MetaWaylandKeyboardGrab;
 typedef struct _MetaWaylandKeyboardGrabInterface MetaWaylandKeyboardGrabInterface;
diff --git a/src/wayland/meta-wayland-wl-shell.c b/src/wayland/meta-wayland-wl-shell.c
index 2a28f48..c3f40bf 100644
--- a/src/wayland/meta-wayland-wl-shell.c
+++ b/src/wayland/meta-wayland-wl-shell.c
@@ -39,9 +39,14 @@ struct _MetaWaylandWlShellSurface
   MetaWaylandSurfaceRoleShellSurface parent;
 };
 
-G_DEFINE_TYPE (MetaWaylandWlShellSurface,
-               meta_wayland_wl_shell_surface,
-               META_TYPE_WAYLAND_SURFACE_ROLE_SHELL_SURFACE);
+static void
+popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaWaylandWlShellSurface,
+                         meta_wayland_wl_shell_surface,
+                         META_TYPE_WAYLAND_SURFACE_ROLE_SHELL_SURFACE,
+                         G_IMPLEMENT_INTERFACE (META_TYPE_WAYLAND_POPUP_SURFACE,
+                                                popup_surface_iface_init));
 
 static void
 sync_wl_shell_parent_relationship (MetaWaylandSurface *surface,
@@ -249,22 +254,16 @@ handle_wl_shell_popup_parent_destroyed (struct wl_listener *listener,
 }
 
 static void
-handle_wl_shell_popup_destroyed (struct wl_listener *listener,
-                                 void               *data)
-{
-  MetaWaylandSurface *surface =
-    wl_container_of (listener, surface, popup.destroy_listener);
-
-  surface->popup.popup = NULL;
-}
-
-static void
 create_popup (MetaWaylandSurface *surface)
 {
+  MetaWaylandWlShellSurface *wl_shell_surface =
+    META_WAYLAND_WL_SHELL_SURFACE (surface->role);
+  MetaWaylandPopupSurface *popup_surface =
+    META_WAYLAND_POPUP_SURFACE (wl_shell_surface);
   MetaWaylandSeat *seat = surface->wl_shell.popup_seat;
   MetaWaylandPopup *popup;
 
-  popup = meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
+  popup = meta_wayland_pointer_start_popup_grab (&seat->pointer, popup_surface);
   if (!popup)
     {
       wl_shell_surface_send_popup_done (surface->wl_shell_surface);
@@ -272,9 +271,6 @@ create_popup (MetaWaylandSurface *surface)
     }
 
   surface->popup.popup = popup;
-  surface->popup.destroy_listener.notify = handle_wl_shell_popup_destroyed;
-  wl_signal_add (meta_wayland_popup_get_destroy_signal (popup),
-                 &surface->popup.destroy_listener);
 }
 
 static void
@@ -583,10 +579,10 @@ wl_shell_surface_role_close (MetaWaylandSurfaceRoleShellSurface *shell_surface_r
 }
 
 static void
-wl_shell_surface_role_popup_done (MetaWaylandSurfaceRoleShellSurface *shell_surface_role)
+meta_wayland_wl_shell_surface_popup_done (MetaWaylandPopupSurface *popup_surface)
 {
   MetaWaylandSurfaceRole *surface_role =
-    META_WAYLAND_SURFACE_ROLE (shell_surface_role);
+    META_WAYLAND_SURFACE_ROLE (popup_surface);
   MetaWaylandSurface *surface =
     meta_wayland_surface_role_get_surface (surface_role);
 
@@ -594,6 +590,36 @@ wl_shell_surface_role_popup_done (MetaWaylandSurfaceRoleShellSurface *shell_surf
 }
 
 static void
+meta_wayland_wl_shell_surface_popup_dismiss (MetaWaylandPopupSurface *popup_surface)
+{
+  MetaWaylandSurfaceRole *surface_role =
+    META_WAYLAND_SURFACE_ROLE (popup_surface);
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+
+  surface->popup.popup = NULL;
+
+  meta_wayland_surface_destroy_window (surface);
+}
+
+static MetaWaylandSurface *
+meta_wayland_wl_shell_surface_popup_get_surface (MetaWaylandPopupSurface *popup_surface)
+{
+  MetaWaylandSurfaceRole *surface_role =
+    META_WAYLAND_SURFACE_ROLE (popup_surface);
+
+  return meta_wayland_surface_role_get_surface (surface_role);
+}
+
+static void
+popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface)
+{
+  iface->done = meta_wayland_wl_shell_surface_popup_done;
+  iface->dismiss = meta_wayland_wl_shell_surface_popup_dismiss;
+  iface->get_surface = meta_wayland_wl_shell_surface_popup_get_surface;
+}
+
+static void
 meta_wayland_wl_shell_surface_init (MetaWaylandWlShellSurface *wl_shell_surface)
 {
 }
@@ -614,7 +640,6 @@ meta_wayland_wl_shell_surface_class_init (MetaWaylandWlShellSurfaceClass *klass)
   shell_surface_role_class->managed = wl_shell_surface_role_managed;
   shell_surface_role_class->ping = wl_shell_surface_role_ping;
   shell_surface_role_class->close = wl_shell_surface_role_close;
-  shell_surface_role_class->popup_done = wl_shell_surface_role_popup_done;
 }
 
 void
diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c
index 541c377..37c7b4d 100644
--- a/src/wayland/meta-wayland-xdg-shell.c
+++ b/src/wayland/meta-wayland-xdg-shell.c
@@ -52,9 +52,14 @@ struct _MetaWaylandXdgPopup
   MetaWaylandSurfaceRoleShellSurface parent;
 };
 
-G_DEFINE_TYPE (MetaWaylandXdgPopup,
-               meta_wayland_xdg_popup,
-               META_TYPE_WAYLAND_SURFACE_ROLE_SHELL_SURFACE);
+static void
+popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaWaylandXdgPopup,
+                         meta_wayland_xdg_popup,
+                         META_TYPE_WAYLAND_SURFACE_ROLE_SHELL_SURFACE,
+                         G_IMPLEMENT_INTERFACE (META_TYPE_WAYLAND_POPUP_SURFACE,
+                                                popup_surface_iface_init));
 
 static void
 xdg_shell_destroy (struct wl_client   *client,
@@ -394,28 +399,6 @@ handle_popup_parent_destroyed (struct wl_listener *listener,
 }
 
 static void
-handle_popup_destroyed (struct wl_listener *listener,
-                        void               *data)
-{
-  MetaWaylandPopup *popup = data;
-  MetaWaylandSurface *top_popup;
-  MetaWaylandSurface *surface =
-    wl_container_of (listener, surface, popup.destroy_listener);
-
-  top_popup = meta_wayland_popup_get_top_popup (popup);
-  if (surface != top_popup)
-    {
-      wl_resource_post_error (surface->xdg_shell_resource,
-                              XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
-                              "destroyed popup not top most popup");
-    }
-
-  surface->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,
@@ -428,6 +411,7 @@ xdg_shell_get_xdg_popup (struct wl_client   *client,
 {
   struct wl_resource *popup_resource;
   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);
@@ -499,7 +483,9 @@ xdg_shell_get_xdg_popup (struct wl_client   *client,
   meta_wayland_surface_set_window (surface, window);
 
   meta_window_focus (window, meta_display_get_current_time (display));
-  popup = meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
+  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 (surface->xdg_popup);
@@ -507,10 +493,7 @@ xdg_shell_get_xdg_popup (struct wl_client   *client,
       return;
     }
 
-  surface->popup.destroy_listener.notify = handle_popup_destroyed;
   surface->popup.popup = popup;
-  wl_signal_add (meta_wayland_popup_get_destroy_signal (popup),
-                 &surface->popup.destroy_listener);
 }
 
 static const struct xdg_shell_interface meta_wayland_xdg_shell_interface = {
@@ -814,10 +797,10 @@ xdg_popup_role_ping (MetaWaylandSurfaceRoleShellSurface *shell_surface_role,
 }
 
 static void
-xdg_popup_role_popup_done (MetaWaylandSurfaceRoleShellSurface *shell_surface_role)
+meta_wayland_xdg_popup_done (MetaWaylandPopupSurface *popup_surface)
 {
   MetaWaylandSurfaceRole *surface_role =
-    META_WAYLAND_SURFACE_ROLE (shell_surface_role);
+    META_WAYLAND_SURFACE_ROLE (popup_surface);
   MetaWaylandSurface *surface =
     meta_wayland_surface_role_get_surface (surface_role);
 
@@ -825,6 +808,45 @@ xdg_popup_role_popup_done (MetaWaylandSurfaceRoleShellSurface *shell_surface_rol
 }
 
 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 (surface->popup.popup);
+  if (surface != top_popup)
+    {
+      wl_resource_post_error (surface->xdg_shell_resource,
+                              XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
+                              "destroyed popup not top most popup");
+    }
+
+  surface->popup.popup = NULL;
+
+  meta_wayland_surface_destroy_window (surface);
+}
+
+static MetaWaylandSurface *
+meta_wayland_xdg_popup_get_surface (MetaWaylandPopupSurface *popup_surface)
+{
+  MetaWaylandSurfaceRole *surface_role =
+    META_WAYLAND_SURFACE_ROLE (popup_surface);
+
+  return meta_wayland_surface_role_get_surface (surface_role);
+}
+
+static void
+popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface)
+{
+  iface->done = meta_wayland_xdg_popup_done;
+  iface->dismiss = meta_wayland_xdg_popup_dismiss;
+  iface->get_surface = meta_wayland_xdg_popup_get_surface;
+}
+
+static void
 meta_wayland_xdg_popup_init (MetaWaylandXdgPopup *role)
 {
 }
@@ -844,7 +866,6 @@ meta_wayland_xdg_popup_class_init (MetaWaylandXdgPopupClass *klass)
   shell_surface_role_class->configure = xdg_popup_role_configure;
   shell_surface_role_class->managed = xdg_popup_role_managed;
   shell_surface_role_class->ping = xdg_popup_role_ping;
-  shell_surface_role_class->popup_done = xdg_popup_role_popup_done;
 }
 
 void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]