Merge branch 'ebassi/issue-4825' into 'main'

Fix crash when running GTK4 apps under Orca

Closes #4825

See merge request GNOME/gtk!4657
This commit is contained in:
Emmanuele Bassi 2022-04-19 21:04:25 +00:00
commit 9761a4758a
4 changed files with 87 additions and 35 deletions

View File

@ -1418,7 +1418,7 @@ gtk_at_spi_context_unregister_object (GtkAtSpiContext *self)
g_clear_pointer (&self->interfaces, g_variant_unref);
}
/* }}} */
/* {{{ GObject boilerplate */
/* {{{ GObject boilerplate */
static void
gtk_at_spi_context_finalize (GObject *gobject)
{
@ -1443,6 +1443,22 @@ gtk_at_spi_context_constructed (GObject *gobject)
static const char *get_bus_address (GdkDisplay *display);
static void
register_object (GtkAtSpiRoot *root,
GtkAtSpiContext *context)
{
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (context));
gtk_atspi_connect_text_signals (accessible,
(GtkAtspiTextChangedCallback *)emit_text_changed,
(GtkAtspiTextSelectionCallback *)emit_text_selection_changed,
context);
gtk_atspi_connect_selection_signals (accessible,
(GtkAtspiSelectionCallback *)emit_selection_changed,
context);
gtk_at_spi_context_register_object (context);
}
static void
gtk_at_spi_context_realize (GtkATContext *context)
{
@ -1489,11 +1505,10 @@ gtk_at_spi_context_realize (GtkATContext *context)
if (self->connection == NULL)
return;
GtkAccessible *accessible = gtk_at_context_get_accessible (context);
#ifdef G_ENABLE_DEBUG
if (GTK_DEBUG_CHECK (A11Y))
{
GtkAccessible *accessible = gtk_at_context_get_accessible (context);
GtkAccessibleRole role = gtk_at_context_get_accessible_role (context);
char *role_name = g_enum_to_string (GTK_TYPE_ACCESSIBLE_ROLE, role);
g_message ("Realizing ATSPI context “%s” for accessible “%s”, with role: “%s”",
@ -1504,16 +1519,7 @@ gtk_at_spi_context_realize (GtkATContext *context)
}
#endif
gtk_atspi_connect_text_signals (accessible,
(GtkAtspiTextChangedCallback *)emit_text_changed,
(GtkAtspiTextSelectionCallback *)emit_text_selection_changed,
self);
gtk_atspi_connect_selection_signals (accessible,
(GtkAtspiSelectionCallback *)emit_selection_changed,
self);
gtk_at_spi_context_register_object (self);
gtk_at_spi_root_queue_register (self->root, self);
gtk_at_spi_root_queue_register (self->root, self, register_object);
}
static void

View File

@ -474,16 +474,24 @@ gtk_at_spi_root_child_changed (GtkAtSpiRoot *self,
window_ref);
}
typedef struct {
GtkAtSpiRoot *root;
GtkAtSpiRootRegisterFunc register_func;
} RegistrationData;
static void
on_registration_reply (GObject *gobject,
GAsyncResult *result,
gpointer user_data)
{
GtkAtSpiRoot *self = user_data;
RegistrationData *data = user_data;
GtkAtSpiRoot *self = data->root;
GError *error = NULL;
GVariant *reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (gobject), result, &error);
self->register_id = 0;
if (error != NULL)
{
g_critical ("Unable to register the application: %s", error->message);
@ -509,19 +517,27 @@ on_registration_reply (GObject *gobject,
/* Drain the list of queued GtkAtSpiContexts, and add them to the cache */
if (self->queued_contexts != NULL)
{
for (GList *l = self->queued_contexts; l != NULL; l = l->next)
gtk_at_spi_cache_add_context (self->cache, l->data);
for (GList *l = g_list_reverse (self->queued_contexts); l != NULL; l = l->next)
{
if (data->register_func != NULL)
data->register_func (self, l->data);
gtk_at_spi_cache_add_context (self->cache, l->data);
}
g_clear_pointer (&self->queued_contexts, g_list_free);
}
self->toplevels = gtk_window_get_toplevels ();
g_free (data);
}
static gboolean
root_register (gpointer data)
root_register (gpointer user_data)
{
GtkAtSpiRoot *self = data;
RegistrationData *data = user_data;
GtkAtSpiRoot *self = data->root;
const char *unique_name;
/* Register the root element; every application has a single root, so we only
@ -577,9 +593,7 @@ root_register (gpointer data)
G_DBUS_CALL_FLAGS_NONE, -1,
NULL,
on_registration_reply,
self);
self->register_id = 0;
data);
return G_SOURCE_REMOVE;
}
@ -587,18 +601,24 @@ root_register (gpointer data)
/*< private >
* gtk_at_spi_root_queue_register:
* @self: a `GtkAtSpiRoot`
* @context: the AtSpi context to register
* @func: the function to call when the root has been registered
*
* Queues the registration of the root object on the AT-SPI bus.
*/
void
gtk_at_spi_root_queue_register (GtkAtSpiRoot *self,
GtkAtSpiContext *context)
gtk_at_spi_root_queue_register (GtkAtSpiRoot *self,
GtkAtSpiContext *context,
GtkAtSpiRootRegisterFunc func)
{
/* The cache is available if the root has finished registering itself; if we
* are still waiting for the registration to finish, add the context to a queue
*/
if (self->cache != NULL)
{
if (func != NULL)
func (self, context);
gtk_at_spi_cache_add_context (self->cache, context);
return;
}
@ -612,7 +632,11 @@ gtk_at_spi_root_queue_register (GtkAtSpiRoot *self,
if (self->register_id != 0)
return;
self->register_id = g_idle_add (root_register, self);
RegistrationData *data = g_new (RegistrationData, 1);
data->root = self;
data->register_func = func;
self->register_id = g_idle_add (root_register, data);
gdk_source_set_static_name_by_id (self->register_id, "[gtk] ATSPI root registration");
}

View File

@ -34,9 +34,13 @@ G_DECLARE_FINAL_TYPE (GtkAtSpiRoot, gtk_at_spi_root, GTK, AT_SPI_ROOT, GObject)
GtkAtSpiRoot *
gtk_at_spi_root_new (const char *bus_address);
typedef void (* GtkAtSpiRootRegisterFunc) (GtkAtSpiRoot *root,
GtkAtSpiContext *context);
void
gtk_at_spi_root_queue_register (GtkAtSpiRoot *self,
GtkAtSpiContext *context);
GtkAtSpiContext *context,
GtkAtSpiRootRegisterFunc func);
void
gtk_at_spi_root_unregister (GtkAtSpiRoot *self,

View File

@ -132,7 +132,9 @@ gtk_image_definition_new_paintable (GdkPaintable *paintable)
GtkImageDefinition *
gtk_image_definition_ref (GtkImageDefinition *def)
{
def->empty.ref_count++;
GtkImageDefinitionEmpty *empty = (GtkImageDefinitionEmpty *) def;
empty->ref_count++;
return def;
}
@ -140,9 +142,11 @@ gtk_image_definition_ref (GtkImageDefinition *def)
void
gtk_image_definition_unref (GtkImageDefinition *def)
{
def->empty.ref_count--;
GtkImageDefinitionEmpty *empty = (GtkImageDefinitionEmpty *) def;
if (def->empty.ref_count > 0)
empty->ref_count--;
if (empty->ref_count > 0)
return;
switch (def->type)
@ -152,13 +156,22 @@ gtk_image_definition_unref (GtkImageDefinition *def)
g_assert_not_reached ();
break;
case GTK_IMAGE_PAINTABLE:
g_object_unref (def->paintable.paintable);
{
GtkImageDefinitionPaintable *paintable = (GtkImageDefinitionPaintable *) def;
g_object_unref (paintable->paintable);
}
break;
case GTK_IMAGE_ICON_NAME:
g_free (def->icon_name.icon_name);
{
GtkImageDefinitionIconName *icon_name = (GtkImageDefinitionIconName *) def;
g_free (icon_name->icon_name);
}
break;
case GTK_IMAGE_GICON:
g_object_unref (def->gicon.gicon);
{
GtkImageDefinitionGIcon *gicon = (GtkImageDefinitionGIcon *) def;
g_object_unref (gicon->gicon);
}
break;
}
@ -189,27 +202,32 @@ gtk_image_definition_get_scale (const GtkImageDefinition *def)
const char *
gtk_image_definition_get_icon_name (const GtkImageDefinition *def)
{
const GtkImageDefinitionIconName *icon_name = (const GtkImageDefinitionIconName *) def;
if (def->type != GTK_IMAGE_ICON_NAME)
return NULL;
return def->icon_name.icon_name;
return icon_name->icon_name;
}
GIcon *
gtk_image_definition_get_gicon (const GtkImageDefinition *def)
{
const GtkImageDefinitionGIcon *gicon = (const GtkImageDefinitionGIcon *) def;
if (def->type != GTK_IMAGE_GICON)
return NULL;
return def->gicon.gicon;
return gicon->gicon;
}
GdkPaintable *
gtk_image_definition_get_paintable (const GtkImageDefinition *def)
{
const GtkImageDefinitionPaintable *paintable = (const GtkImageDefinitionPaintable *) def;
if (def->type != GTK_IMAGE_PAINTABLE)
return NULL;
return def->paintable.paintable;
return paintable->paintable;
}