x11/display: Delay cursor updates

When a client (either Wayland or X11) is started, the window activation
will update the cursor to the "busy" cursor.

Mutter will then set the X11 cursor on the X11 root window to match that
so that X11 applications which do not explicitly set a cursor inherit
from that default (busy) cursor.

Updating the X11 cursor too often can hammer the X11 connection and
cause a deadlock with Xwayland.

Reload the X11 cursor in a later handler to avoid that issue.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2849>
This commit is contained in:
Olivier Fourdan 2023-02-16 09:43:37 +01:00 committed by Marge Bot
parent 734b72099a
commit 5e7754f742
2 changed files with 47 additions and 1 deletions

View File

@ -206,6 +206,8 @@ struct _MetaX11Display
MetaX11Stack *x11_stack; MetaX11Stack *x11_stack;
XserverRegion empty_region; XserverRegion empty_region;
unsigned int reload_x11_cursor_later;
}; };
MetaX11Display *meta_x11_display_new (MetaDisplay *display, GError **error); MetaX11Display *meta_x11_display_new (MetaDisplay *display, GError **error);

View File

@ -103,6 +103,8 @@ static void prefs_changed_callback (MetaPreference pref,
static void meta_x11_display_init_frames_client (MetaX11Display *x11_display); static void meta_x11_display_init_frames_client (MetaX11Display *x11_display);
static void meta_x11_display_remove_cursor_later (MetaX11Display *x11_display);
static MetaBackend * static MetaBackend *
backend_from_x11_display (MetaX11Display *x11_display) backend_from_x11_display (MetaX11Display *x11_display)
{ {
@ -274,6 +276,8 @@ meta_x11_display_dispose (GObject *object)
g_clear_handle_id (&x11_display->display_close_idle, g_source_remove); g_clear_handle_id (&x11_display->display_close_idle, g_source_remove);
meta_x11_display_remove_cursor_later (x11_display);
g_free (x11_display->name); g_free (x11_display->name);
x11_display->name = NULL; x11_display->name = NULL;
@ -1601,13 +1605,53 @@ set_cursor_theme (Display *xdisplay,
meta_prefs_get_cursor_size () * scale); meta_prefs_get_cursor_size () * scale);
} }
static void
meta_x11_display_remove_cursor_later (MetaX11Display *x11_display)
{
if (x11_display->reload_x11_cursor_later)
{
MetaDisplay *display = x11_display->display;
MetaLaters *laters = meta_compositor_get_laters (display->compositor);
meta_laters_remove (laters, x11_display->reload_x11_cursor_later);
x11_display->reload_x11_cursor_later = 0;
}
}
static gboolean
reload_x11_cursor_later (gpointer user_data)
{
MetaX11Display *x11_display = user_data;
x11_display->reload_x11_cursor_later = 0;
meta_x11_display_reload_cursor (x11_display);
return G_SOURCE_REMOVE;
}
static void
schedule_reload_x11_cursor (MetaX11Display *x11_display)
{
MetaDisplay *display = x11_display->display;
MetaLaters *laters = meta_compositor_get_laters (display->compositor);
if (x11_display->reload_x11_cursor_later)
return;
x11_display->reload_x11_cursor_later =
meta_laters_add (laters, META_LATER_BEFORE_REDRAW,
reload_x11_cursor_later,
x11_display,
NULL);
}
static void static void
update_cursor_theme (MetaX11Display *x11_display) update_cursor_theme (MetaX11Display *x11_display)
{ {
MetaBackend *backend = backend_from_x11_display (x11_display); MetaBackend *backend = backend_from_x11_display (x11_display);
set_cursor_theme (x11_display->xdisplay, backend); set_cursor_theme (x11_display->xdisplay, backend);
meta_x11_display_reload_cursor (x11_display); schedule_reload_x11_cursor (x11_display);
if (META_IS_BACKEND_X11 (backend)) if (META_IS_BACKEND_X11 (backend))
{ {