[mutter] wayland: Fail clients who try to create or destroy a not-top-most popup



commit 9a99a80710921105f1c316b4da0eafda04a720b9
Author: Jonas Ådahl <jadahl gmail com>
Date:   Thu Feb 12 11:20:52 2015 +0800

    wayland: Fail clients who try to create or destroy a not-top-most popup
    
    If a client creates an xdg_popup given a parent that is a xdg_popup that
    is not the most top one in the grab chain, send the
    not_the_topmost_popup error.
    
    Also fail a client who destroys a popup that is not the top most one.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=744452

 src/wayland/meta-wayland-pointer.c |   12 ++++++++++++
 src/wayland/meta-wayland-pointer.h |    2 ++
 src/wayland/meta-wayland-popup.c   |   17 +++++++++++++++++
 src/wayland/meta-wayland-popup.h   |    4 ++++
 src/wayland/meta-wayland-surface.c |   21 +++++++++++++++++++++
 5 files changed, 56 insertions(+), 0 deletions(-)
---
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 5905cb9..1531a4a 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -741,3 +741,15 @@ meta_wayland_pointer_can_popup (MetaWaylandPointer *pointer, uint32_t serial)
 {
   return pointer->grab_serial == serial;
 }
+
+MetaWaylandSurface *
+meta_wayland_pointer_get_top_popup (MetaWaylandPointer *pointer)
+{
+  MetaWaylandPopupGrab *grab;
+
+  if (!meta_wayland_pointer_grab_is_popup_grab (pointer->grab))
+    return NULL;
+
+  grab = (MetaWaylandPopupGrab*)pointer->grab;
+  return meta_wayland_popup_grab_get_top_popup(grab);
+}
diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h
index 60125ac..70b7b42 100644
--- a/src/wayland/meta-wayland-pointer.h
+++ b/src/wayland/meta-wayland-pointer.h
@@ -125,4 +125,6 @@ gboolean meta_wayland_pointer_can_grab_surface (MetaWaylandPointer *pointer,
 gboolean meta_wayland_pointer_can_popup (MetaWaylandPointer *pointer,
                                          uint32_t            serial);
 
+MetaWaylandSurface *meta_wayland_pointer_get_top_popup (MetaWaylandPointer *pointer);
+
 #endif /* META_WAYLAND_POINTER_H */
diff --git a/src/wayland/meta-wayland-popup.c b/src/wayland/meta-wayland-popup.c
index cc8b4bd..f3d47ae 100644
--- a/src/wayland/meta-wayland-popup.c
+++ b/src/wayland/meta-wayland-popup.c
@@ -172,6 +172,17 @@ meta_wayland_popup_grab_end (MetaWaylandPopupGrab *grab)
   meta_wayland_pointer_end_grab (grab->generic.pointer);
 }
 
+MetaWaylandSurface *
+meta_wayland_popup_grab_get_top_popup (MetaWaylandPopupGrab *grab)
+{
+  MetaWaylandPopup *popup;
+
+  g_assert (!wl_list_empty (&grab->all_popups));
+  popup = wl_container_of (grab->all_popups.next, popup, link);
+
+  return popup->surface;
+}
+
 gboolean
 meta_wayland_pointer_grab_is_popup_grab (MetaWaylandPointerGrab *grab)
 {
@@ -199,6 +210,12 @@ meta_wayland_popup_dismiss (MetaWaylandPopup *popup)
     meta_wayland_pointer_end_popup_grab (popup_grab->generic.pointer);
 }
 
+MetaWaylandSurface *
+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)
 {
diff --git a/src/wayland/meta-wayland-popup.h b/src/wayland/meta-wayland-popup.h
index 7082225..0bee220 100644
--- a/src/wayland/meta-wayland-popup.h
+++ b/src/wayland/meta-wayland-popup.h
@@ -37,6 +37,8 @@ void meta_wayland_popup_grab_begin (MetaWaylandPopupGrab *grab,
 
 void meta_wayland_popup_grab_end (MetaWaylandPopupGrab *grab);
 
+MetaWaylandSurface *meta_wayland_popup_grab_get_top_popup (MetaWaylandPopupGrab *grab);
+
 gboolean meta_wayland_pointer_grab_is_popup_grab (MetaWaylandPointerGrab *grab);
 
 MetaWaylandPopup *meta_wayland_popup_create (MetaWaylandSurface   *surface,
@@ -46,6 +48,8 @@ void meta_wayland_popup_destroy (MetaWaylandPopup *popup);
 
 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 6751301..b1364e8 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -1041,9 +1041,19 @@ static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = {
 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_popup,
+                              XDG_POPUP_ERROR_NOT_THE_TOPMOST_POPUP,
+                              "destroyed popup not top most popup");
+    }
+
   surface->popup.popup = NULL;
 
   destroy_window (surface);
@@ -1063,6 +1073,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
   struct wl_resource *popup_resource;
   MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
   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 ();
@@ -1093,6 +1104,16 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
       return;
     }
 
+  top_popup = meta_wayland_pointer_get_top_popup (&seat->pointer);
+  if ((top_popup == NULL && parent_surf->xdg_surface == NULL) ||
+      (top_popup != NULL && parent_surf != top_popup))
+    {
+      wl_resource_post_error (resource,
+                              XDG_POPUP_ERROR_NOT_THE_TOPMOST_POPUP,
+                              "parent not top most surface");
+      return;
+    }
+
   popup_resource = wl_resource_create (client, &xdg_popup_interface,
                                        wl_resource_get_version (resource), id);
   wl_resource_set_implementation (popup_resource,


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