wayland: Unmap popup windows when a popup chain is dismissed
When dismissing a popup grab, always unmap every popup window in the chain, instead of relying on the surfaces and xdg_popups being destroyed. https://bugzilla.gnome.org/show_bug.cgi?id=744452
This commit is contained in:
parent
768286bffb
commit
be77874ec9
@ -581,7 +581,7 @@ meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
|
||||
meta_wayland_popup_grab_destroy (popup_grab);
|
||||
}
|
||||
|
||||
gboolean
|
||||
MetaWaylandPopup *
|
||||
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
@ -589,7 +589,7 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
|
||||
if (pointer->grab != &pointer->default_grab &&
|
||||
!meta_wayland_pointer_grab_is_popup_grab (pointer->grab))
|
||||
return FALSE;
|
||||
return NULL;
|
||||
|
||||
if (pointer->grab == &pointer->default_grab)
|
||||
{
|
||||
@ -601,10 +601,7 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
else
|
||||
grab = (MetaWaylandPopupGrab*)pointer->grab;
|
||||
|
||||
if (meta_wayland_popup_create (surface, grab) == NULL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
return meta_wayland_popup_create (surface, grab);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -99,8 +99,8 @@ void meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
||||
|
||||
void meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer);
|
||||
|
||||
gboolean meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *popup);
|
||||
MetaWaylandPopup *meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *popup);
|
||||
|
||||
void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer);
|
||||
|
||||
|
@ -61,6 +61,7 @@ struct _MetaWaylandPopup
|
||||
MetaWaylandPopupGrab *grab;
|
||||
MetaWaylandSurface *surface;
|
||||
struct wl_listener surface_destroy_listener;
|
||||
struct wl_signal destroy_signal;
|
||||
|
||||
struct wl_list link;
|
||||
};
|
||||
@ -180,6 +181,8 @@ meta_wayland_pointer_grab_is_popup_grab (MetaWaylandPointerGrab *grab)
|
||||
void
|
||||
meta_wayland_popup_destroy (MetaWaylandPopup *popup)
|
||||
{
|
||||
wl_signal_emit (&popup->destroy_signal, popup);
|
||||
|
||||
wl_list_remove (&popup->surface_destroy_listener.link);
|
||||
wl_list_remove (&popup->link);
|
||||
g_slice_free (MetaWaylandPopup, popup);
|
||||
@ -196,6 +199,12 @@ meta_wayland_popup_dismiss (MetaWaylandPopup *popup)
|
||||
meta_wayland_pointer_end_popup_grab (popup_grab->generic.pointer);
|
||||
}
|
||||
|
||||
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)
|
||||
@ -220,6 +229,7 @@ meta_wayland_popup_create (MetaWaylandSurface *surface,
|
||||
popup->grab = grab;
|
||||
popup->surface = surface;
|
||||
popup->surface_destroy_listener.notify = on_popup_surface_destroy;
|
||||
wl_signal_init (&popup->destroy_signal);
|
||||
|
||||
if (surface->xdg_popup)
|
||||
{
|
||||
|
@ -46,4 +46,6 @@ void meta_wayland_popup_destroy (MetaWaylandPopup *popup);
|
||||
|
||||
void meta_wayland_popup_dismiss (MetaWaylandPopup *popup);
|
||||
|
||||
struct wl_signal *meta_wayland_popup_get_destroy_signal (MetaWaylandPopup *popup);
|
||||
|
||||
#endif /* META_WAYLAND_POPUP_H */
|
||||
|
@ -1021,7 +1021,9 @@ xdg_popup_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_window (surface);
|
||||
if (surface->popup.popup)
|
||||
meta_wayland_popup_dismiss (surface->popup.popup);
|
||||
|
||||
surface->xdg_popup = NULL;
|
||||
}
|
||||
|
||||
@ -1036,6 +1038,17 @@ static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = {
|
||||
xdg_popup_destroy,
|
||||
};
|
||||
|
||||
static void
|
||||
handle_popup_destroyed (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandSurface *surface =
|
||||
wl_container_of (listener, surface, popup.destroy_listener);
|
||||
|
||||
surface->popup.popup = NULL;
|
||||
|
||||
destroy_window (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
@ -1053,6 +1066,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWindow *window;
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaWaylandPopup *popup;
|
||||
|
||||
if (parent_surf == NULL || parent_surf->window == NULL)
|
||||
return;
|
||||
@ -1107,7 +1121,17 @@ 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));
|
||||
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
|
||||
popup = meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
|
||||
if (popup == NULL)
|
||||
{
|
||||
destroy_window (surface);
|
||||
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 = {
|
||||
|
@ -100,6 +100,12 @@ struct _MetaWaylandSurface
|
||||
MetaWaylandSerial acked_configure_serial;
|
||||
gboolean has_set_geometry;
|
||||
|
||||
/* xdg_popup */
|
||||
struct {
|
||||
MetaWaylandPopup *popup;
|
||||
struct wl_listener destroy_listener;
|
||||
} popup;
|
||||
|
||||
/* wl_subsurface stuff. */
|
||||
struct {
|
||||
MetaWaylandSurface *parent;
|
||||
|
Loading…
Reference in New Issue
Block a user