[java-atk-wrapper: 1/2] Make sure atk objects exist while processing signals



commit 355a91eaae8fb9f4d546ee7d1efc4aa527dfc322
Author: Samuel Thibault <samuel thibault ens-lyon org>
Date:   Mon Apr 1 23:41:27 2019 +0200

    Make sure atk objects exist while processing signals
    
    Since we have to avoid calling methods of applications objects, we can't
    afford unreferencing from the jaw thread. This change thus makes it just
    queue the para struct to be freed, so it's all processed in the application
    when it makes the next accessibility call.
    
    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=793543

 jni/src/AtkWrapper.c | 88 ++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 68 insertions(+), 20 deletions(-)
---
diff --git a/jni/src/AtkWrapper.c b/jni/src/AtkWrapper.c
index d190674..c180fab 100644
--- a/jni/src/AtkWrapper.c
+++ b/jni/src/AtkWrapper.c
@@ -204,6 +204,7 @@ alloc_callback_para (JNIEnv *jniEnv, jobject ac)
       g_warning("\nalloc_callback_para: jaw_impl == NULL\n");
     return NULL;
   }
+  g_object_ref(G_OBJECT(jaw_impl));
   CallbackPara *para = g_new(CallbackPara, 1);
   para->global_ac = ac;
   para->jaw_impl = jaw_impl;
@@ -231,6 +232,8 @@ free_callback_para (CallbackPara *para)
 
   (*jniEnv)->DeleteGlobalRef(jniEnv, para->global_ac);
 
+  g_object_unref(G_OBJECT(para->jaw_impl));
+
   if (para->args) {
     (*jniEnv)->DeleteGlobalRef(jniEnv, para->args);
   }
@@ -238,6 +241,36 @@ free_callback_para (CallbackPara *para)
   g_free(para);
 }
 
+/* List of callback params to be freed */
+static GSList *callback_para_frees;
+static GMutex callback_para_frees_mutex;
+
+/* Add a note that this callback param should be freed from the application */
+static void queue_free_callback_para(CallbackPara *para)
+{
+  g_mutex_lock(&callback_para_frees_mutex);
+  callback_para_frees = g_slist_prepend(callback_para_frees, para);
+  g_mutex_unlock(&callback_para_frees_mutex);
+}
+
+/* Process the unreference requests */
+static void callback_para_process_frees(void)
+{
+  GSList *list, *cur, *next;
+
+  g_mutex_lock(&callback_para_frees_mutex);
+  list = callback_para_frees;
+  callback_para_frees = NULL;
+  g_mutex_unlock(&callback_para_frees_mutex);
+
+  for (cur = list; cur != NULL; cur = next)
+  {
+    free_callback_para(cur->data);
+    next = g_slist_next(cur);
+    g_slist_free_1(cur);
+  }
+}
+
 static gboolean
 focus_notify_handler (gpointer p)
 {
@@ -248,7 +281,7 @@ focus_notify_handler (gpointer p)
                                  ATK_STATE_SHOWING,
                                  1);
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -264,6 +297,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_focusNotify(JNIEnv *jniEnv,
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   jni_main_idle_add(focus_notify_handler, para);
 }
@@ -278,13 +312,13 @@ window_open_handler (gpointer p)
   if (!g_strcmp0(atk_role_get_name(atk_object_get_role(atk_obj)),
                  "redundant object"))
   {
-    free_callback_para(para);
+    queue_free_callback_para(para);
     return G_SOURCE_REMOVE;
   }
 
   if (atk_object_get_role(atk_obj) == ATK_ROLE_TOOL_TIP)
   {
-    free_callback_para(para);
+    queue_free_callback_para(para);
     return G_SOURCE_REMOVE;
   }
 
@@ -303,7 +337,7 @@ window_open_handler (gpointer p)
     g_signal_emit_by_name(atk_obj, "create", 0);
   }
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -320,6 +354,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_windowOpen(JNIEnv *jniEnv,
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   para->is_toplevel = (jIsToplevel == JNI_TRUE) ? TRUE : FALSE;
   jni_main_idle_add(window_open_handler, para);
@@ -334,13 +369,13 @@ window_close_handler (gpointer p)
 
   if (!g_strcmp0(atk_role_get_name(atk_object_get_role(atk_obj)), "redundant object"))
   {
-    free_callback_para(para);
+    queue_free_callback_para(para);
     return G_SOURCE_REMOVE;
   }
 
   if (atk_object_get_role(atk_obj) == ATK_ROLE_TOOL_TIP)
   {
-    free_callback_para(para);
+    queue_free_callback_para(para);
     return G_SOURCE_REMOVE;
   }
 
@@ -358,7 +393,7 @@ window_close_handler (gpointer p)
     g_signal_emit_by_name(atk_obj, "destroy", 0);
   }
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -375,6 +410,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_windowClose(JNIEnv *jniEnv,
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   para->is_toplevel = (jIsToplevel == JNI_TRUE) ? TRUE : FALSE;
   jni_main_idle_add(window_close_handler, para);
@@ -388,7 +424,7 @@ window_minimize_handler (gpointer p)
 
   g_signal_emit_by_name(atk_obj, "minimize", 0);
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -404,6 +440,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_windowMinimize(JNIEnv *jniEnv,
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   jni_main_idle_add(window_minimize_handler, para);
 }
@@ -416,7 +453,7 @@ window_maximize_handler (gpointer p)
 
   g_signal_emit_by_name(atk_obj, "maximize", 0);
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -431,6 +468,7 @@ JNIEXPORT void JNICALL Java_org_GNOME_Accessibility_AtkWrapper_windowMaximize(JN
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac );
   jni_main_idle_add(window_maximize_handler, para);
 }
@@ -443,7 +481,7 @@ window_restore_handler (gpointer p)
 
   g_signal_emit_by_name(atk_obj, "restore", 0);
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -458,6 +496,7 @@ JNIEXPORT void JNICALL Java_org_GNOME_Accessibility_AtkWrapper_windowRestore(JNI
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   jni_main_idle_add(window_restore_handler, para);
 }
@@ -470,7 +509,7 @@ window_activate_handler (gpointer p)
 
   g_signal_emit_by_name(atk_obj, "activate", 0);
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -485,6 +524,7 @@ JNIEXPORT void JNICALL Java_org_GNOME_Accessibility_AtkWrapper_windowActivate(JN
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   jni_main_idle_add(window_activate_handler, para);
 }
@@ -497,7 +537,7 @@ window_deactivate_handler (gpointer p)
 
   g_signal_emit_by_name(atk_obj, "deactivate", 0);
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -513,6 +553,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_windowDeactivate(JNIEnv *jniEnv,
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   jni_main_idle_add(window_deactivate_handler, para);
 }
@@ -525,7 +566,7 @@ window_state_change_handler (gpointer p)
 
   g_signal_emit_by_name(atk_obj, "state-change", 0);
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -541,6 +582,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_windowStateChange(JNIEnv *jniEnv
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   jni_main_idle_add(window_state_change_handler, para);
 }
@@ -776,7 +818,7 @@ signal_emit_handler (gpointer p)
     default:
       break;
   }
-  free_callback_para(para);
+  queue_free_callback_para(para);
   return G_SOURCE_REMOVE;
 }
 
@@ -793,6 +835,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_emitSignal(JNIEnv *jniEnv,
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   jobjectArray global_args = (jobjectArray)(*jniEnv)->NewGlobalRef(jniEnv, args);
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   para->signal_id = (gint)id;
@@ -861,7 +904,7 @@ object_state_change_handler (gpointer p)
                                  para->atk_state,
                                  para->state_value);
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
   return G_SOURCE_REMOVE;
 }
 
@@ -878,6 +921,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_objectStateChange(JNIEnv *jniEnv
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   AtkStateType state_type = jaw_util_get_atk_state_type_from_java_state( jniEnv, state );
   para->atk_state = state_type;
@@ -902,7 +946,7 @@ component_added_handler (gpointer p)
                                    1);
   }
 
-  free_callback_para(para);
+  queue_free_callback_para(para);
   return G_SOURCE_REMOVE;
 }
 
@@ -917,6 +961,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_componentAdded(JNIEnv *jniEnv,
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   jni_main_idle_add(component_added_handler, para);
 }
@@ -931,12 +976,12 @@ component_removed_handler (gpointer p)
   {
     if (jaw_debug)
       g_warning("component_removed_handler: atk_obj == NULL");
-    free_callback_para(para);
+    queue_free_callback_para(para);
     return G_SOURCE_REMOVE;
   }
   if (atk_object_get_role(atk_obj) == ATK_ROLE_TOOL_TIP)
     atk_object_notify_state_change(atk_obj, ATK_STATE_SHOWING, FALSE);
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -952,6 +997,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_componentRemoved(JNIEnv *jniEnv,
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   jni_main_idle_add(component_removed_handler, para);
 }
@@ -969,11 +1015,11 @@ bounds_changed_handler (gpointer p)
   {
     if (jaw_debug)
       g_warning("bounds_changed_handler: atk_obj == NULL");
-    free_callback_para(para);
+    queue_free_callback_para(para);
     return G_SOURCE_REMOVE;
   }
   g_signal_emit_by_name(atk_obj, "bounds_changed");
-  free_callback_para(para);
+  queue_free_callback_para(para);
 
   return G_SOURCE_REMOVE;
 }
@@ -989,6 +1035,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_boundsChanged(JNIEnv *jniEnv,
     return;
   }
   jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, jAccContext);
+  callback_para_process_frees();
   CallbackPara *para = alloc_callback_para(jniEnv, global_ac);
   jni_main_idle_add(bounds_changed_handler, para);
 }
@@ -1108,6 +1155,7 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_dispatchKeyEvent(JNIEnv *jniEnv,
 {
   jboolean key_consumed;
   jobject global_key_event = (*jniEnv)->NewGlobalRef(jniEnv, jAtkKeyEvent);
+  callback_para_process_frees();
   jni_main_idle_add(key_dispatch_handler, (gpointer)global_key_event);
 
   if(jaw_debug)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]