gtksettings: Remove display from cache on closing
GTK caches the settings per display in a static `GArray`, keeping a
reference to the `GdkDisplay` as the key.
However, when closing the display, the corresponding entry is not
removed from the cache in `GtkSettings`.
So when reopening again a `GdkDisplay`, if the new address matches one
of the previously closed display, the cache will return the existing
`GtkSettings` from the cache, which still holds a reference to the old
`GdkScreen` which was freed along the `GdkDisplay`.
To avoid the issue, make sure to remove the `GdkDisplay` and
corresponding `GdkSettings` when closing the `GdkDisplay`.
Also, care must be taken not to recreate the `GdkSettings` and re-add
the `GdkDisplay` to the cache once the display is closed, and make sure
callers of `gtk_settings_get_for_display()` can deal with a returned
value being `NULL` if the display is closed.
Fixes: commit 360a3c1690
- "Use a cheaper way to store settings per
display"
This commit is contained in:
parent
c9601f1567
commit
b1d55f2c85
@ -608,9 +608,10 @@ unset_screen (GtkIconTheme *icon_theme)
|
||||
g_signal_handlers_disconnect_by_func (display,
|
||||
(gpointer) display_closed,
|
||||
icon_theme);
|
||||
g_signal_handlers_disconnect_by_func (settings,
|
||||
(gpointer) theme_changed,
|
||||
icon_theme);
|
||||
if (settings)
|
||||
g_signal_handlers_disconnect_by_func (settings,
|
||||
(gpointer) theme_changed,
|
||||
icon_theme);
|
||||
|
||||
priv->screen = NULL;
|
||||
}
|
||||
|
@ -463,10 +463,10 @@ display_closed_cb (GdkDisplay *display,
|
||||
|
||||
screen = gdk_display_get_default_screen (display);
|
||||
settings = gtk_settings_get_for_screen (screen);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (settings),
|
||||
I_("gtk-modules"),
|
||||
NULL, NULL);
|
||||
if (settings)
|
||||
g_object_set_data_full (G_OBJECT (settings),
|
||||
I_("gtk-modules"),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1900,6 +1900,29 @@ settings_init_style (GtkSettings *settings)
|
||||
settings_update_key_theme (settings);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_display_closed (GdkDisplay *display,
|
||||
gboolean is_error,
|
||||
gpointer data)
|
||||
{
|
||||
DisplaySettings *ds;
|
||||
int i;
|
||||
|
||||
if (G_UNLIKELY (display_settings == NULL))
|
||||
return;
|
||||
|
||||
ds = (DisplaySettings *)display_settings->data;
|
||||
for (i = 0; i < display_settings->len; i++)
|
||||
{
|
||||
if (ds[i].display == display)
|
||||
{
|
||||
g_clear_object (&ds[i].settings);
|
||||
display_settings = g_array_remove_index_fast (display_settings, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GtkSettings *
|
||||
gtk_settings_create_for_display (GdkDisplay *display)
|
||||
{
|
||||
@ -1955,7 +1978,9 @@ gtk_settings_create_for_display (GdkDisplay *display)
|
||||
|
||||
v.display = display;
|
||||
v.settings = settings;
|
||||
g_array_append_val (display_settings, v);
|
||||
display_settings = g_array_append_val (display_settings, v);
|
||||
g_signal_connect (display, "closed",
|
||||
G_CALLBACK (settings_display_closed), NULL);
|
||||
|
||||
settings_init_style (settings);
|
||||
settings_update_xsettings (settings);
|
||||
@ -1975,6 +2000,10 @@ gtk_settings_get_for_display (GdkDisplay *display)
|
||||
DisplaySettings *ds;
|
||||
int i;
|
||||
|
||||
/* If the display is closed, we don't want to recreate the settings! */
|
||||
if G_UNLIKELY (gdk_display_is_closed (display))
|
||||
return NULL;
|
||||
|
||||
if G_UNLIKELY (display_settings == NULL)
|
||||
display_settings = g_array_new (FALSE, TRUE, sizeof (DisplaySettings));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user