mirror of
https://github.com/brl/mutter.git
synced 2024-12-01 12:20:47 -05:00
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);
|
meta_wayland_popup_grab_destroy (popup_grab);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
MetaWaylandPopup *
|
||||||
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||||
MetaWaylandSurface *surface)
|
MetaWaylandSurface *surface)
|
||||||
{
|
{
|
||||||
@ -589,7 +589,7 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
|||||||
|
|
||||||
if (pointer->grab != &pointer->default_grab &&
|
if (pointer->grab != &pointer->default_grab &&
|
||||||
!meta_wayland_pointer_grab_is_popup_grab (pointer->grab))
|
!meta_wayland_pointer_grab_is_popup_grab (pointer->grab))
|
||||||
return FALSE;
|
return NULL;
|
||||||
|
|
||||||
if (pointer->grab == &pointer->default_grab)
|
if (pointer->grab == &pointer->default_grab)
|
||||||
{
|
{
|
||||||
@ -601,10 +601,7 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
|||||||
else
|
else
|
||||||
grab = (MetaWaylandPopupGrab*)pointer->grab;
|
grab = (MetaWaylandPopupGrab*)pointer->grab;
|
||||||
|
|
||||||
if (meta_wayland_popup_create (surface, grab) == NULL)
|
return meta_wayland_popup_create (surface, grab);
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -99,7 +99,7 @@ void meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
|||||||
|
|
||||||
void meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer);
|
void meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer);
|
||||||
|
|
||||||
gboolean meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
MetaWaylandPopup *meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||||
MetaWaylandSurface *popup);
|
MetaWaylandSurface *popup);
|
||||||
|
|
||||||
void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer);
|
void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer);
|
||||||
|
@ -61,6 +61,7 @@ struct _MetaWaylandPopup
|
|||||||
MetaWaylandPopupGrab *grab;
|
MetaWaylandPopupGrab *grab;
|
||||||
MetaWaylandSurface *surface;
|
MetaWaylandSurface *surface;
|
||||||
struct wl_listener surface_destroy_listener;
|
struct wl_listener surface_destroy_listener;
|
||||||
|
struct wl_signal destroy_signal;
|
||||||
|
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
@ -180,6 +181,8 @@ meta_wayland_pointer_grab_is_popup_grab (MetaWaylandPointerGrab *grab)
|
|||||||
void
|
void
|
||||||
meta_wayland_popup_destroy (MetaWaylandPopup *popup)
|
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->surface_destroy_listener.link);
|
||||||
wl_list_remove (&popup->link);
|
wl_list_remove (&popup->link);
|
||||||
g_slice_free (MetaWaylandPopup, popup);
|
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);
|
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
|
static void
|
||||||
on_popup_surface_destroy (struct wl_listener *listener,
|
on_popup_surface_destroy (struct wl_listener *listener,
|
||||||
void *data)
|
void *data)
|
||||||
@ -220,6 +229,7 @@ meta_wayland_popup_create (MetaWaylandSurface *surface,
|
|||||||
popup->grab = grab;
|
popup->grab = grab;
|
||||||
popup->surface = surface;
|
popup->surface = surface;
|
||||||
popup->surface_destroy_listener.notify = on_popup_surface_destroy;
|
popup->surface_destroy_listener.notify = on_popup_surface_destroy;
|
||||||
|
wl_signal_init (&popup->destroy_signal);
|
||||||
|
|
||||||
if (surface->xdg_popup)
|
if (surface->xdg_popup)
|
||||||
{
|
{
|
||||||
|
@ -46,4 +46,6 @@ void meta_wayland_popup_destroy (MetaWaylandPopup *popup);
|
|||||||
|
|
||||||
void meta_wayland_popup_dismiss (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 */
|
#endif /* META_WAYLAND_POPUP_H */
|
||||||
|
@ -1021,7 +1021,9 @@ xdg_popup_destructor (struct wl_resource *resource)
|
|||||||
{
|
{
|
||||||
MetaWaylandSurface *surface = wl_resource_get_user_data (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;
|
surface->xdg_popup = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1036,6 +1038,17 @@ static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = {
|
|||||||
xdg_popup_destroy,
|
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
|
static void
|
||||||
xdg_shell_get_xdg_popup (struct wl_client *client,
|
xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
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);
|
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
MetaDisplay *display = meta_get_display ();
|
MetaDisplay *display = meta_get_display ();
|
||||||
|
MetaWaylandPopup *popup;
|
||||||
|
|
||||||
if (parent_surf == NULL || parent_surf->window == NULL)
|
if (parent_surf == NULL || parent_surf->window == NULL)
|
||||||
return;
|
return;
|
||||||
@ -1107,7 +1121,17 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
|||||||
meta_wayland_surface_set_window (surface, window);
|
meta_wayland_surface_set_window (surface, window);
|
||||||
|
|
||||||
meta_window_focus (window, meta_display_get_current_time (display));
|
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 = {
|
static const struct xdg_shell_interface meta_wayland_xdg_shell_interface = {
|
||||||
|
@ -100,6 +100,12 @@ struct _MetaWaylandSurface
|
|||||||
MetaWaylandSerial acked_configure_serial;
|
MetaWaylandSerial acked_configure_serial;
|
||||||
gboolean has_set_geometry;
|
gboolean has_set_geometry;
|
||||||
|
|
||||||
|
/* xdg_popup */
|
||||||
|
struct {
|
||||||
|
MetaWaylandPopup *popup;
|
||||||
|
struct wl_listener destroy_listener;
|
||||||
|
} popup;
|
||||||
|
|
||||||
/* wl_subsurface stuff. */
|
/* wl_subsurface stuff. */
|
||||||
struct {
|
struct {
|
||||||
MetaWaylandSurface *parent;
|
MetaWaylandSurface *parent;
|
||||||
|
Loading…
Reference in New Issue
Block a user