summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2015-02-12 11:20:52 +0800
committerJonas Ådahl <jadahl@gmail.com>2015-02-17 22:14:47 +0800
commit9a99a80710921105f1c316b4da0eafda04a720b9 (patch)
treeb526b315b5f376c023c1f6bb88574f6fcec471e8
parentbe77874ec92dd7ff936955ac89ce67db5edc2a08 (diff)
downloadmutter-9a99a80710921105f1c316b4da0eafda04a720b9.tar.gz
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
-rw-r--r--src/wayland/meta-wayland-pointer.c12
-rw-r--r--src/wayland/meta-wayland-pointer.h2
-rw-r--r--src/wayland/meta-wayland-popup.c17
-rw-r--r--src/wayland/meta-wayland-popup.h4
-rw-r--r--src/wayland/meta-wayland-surface.c21
5 files changed, 56 insertions, 0 deletions
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 5905cb95c..1531a4a00 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 60125ace7..70b7b427a 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 cc8b4bd8d..f3d47aef7 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 70822250d..0bee220d4 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 67513014e..b1364e8c6 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,