? 88033patch
? Keyboard.kbd
? event-listener-test.out
? gok.out
? gok.out1
? gok.out2
Index: gok/gok-spy-priv.h
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-spy-priv.h,v
retrieving revision 1.8
diff -u -r1.8 gok-spy-priv.h
--- gok/gok-spy-priv.h	6 Jan 2003 20:19:46 -0000	1.8
+++ gok/gok-spy-priv.h	14 Mar 2003 20:21:49 -0000
@@ -31,7 +31,12 @@
 #include <libspi/accessible.h>
 #include <libspi/application.h>
 
-enum gokevents { GOKSPY_FOCUS_EVENT, GOKSPY_DEFUNCT_EVENT };
+enum gokevents {
+GOKSPY_FOCUS_EVENT,
+GOKSPY_DEFUNCT_EVENT,
+GOKSPY_WINDOW_ACTIVATE_EVENT,
+GOKSPY_WINDOW_DEACTIVATE_EVENT
+};
 
 /* this structure used in the creation of a linked list of Accessible*, char* (name) pairs */
 typedef struct AccessibleNode
Index: gok/gok-spy.c
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-spy.c,v
retrieving revision 1.55
diff -u -r1.55 gok-spy.c
--- gok/gok-spy.c	13 Mar 2003 11:13:51 -0000	1.55
+++ gok/gok-spy.c	14 Mar 2003 20:21:49 -0000
@@ -93,6 +93,12 @@
 
 static gboolean gok_spy_worth_searching (Accessible* accessible);
 
+static void gok_spy_window_activate_listener (const AccessibleEvent *event,
+                                              void *user_data);
+
+static void gok_spy_window_deactivate_listener (const AccessibleEvent *event,
+                                                void *user_data);
+
 /*
  * gok-spy variables
  */
@@ -112,6 +118,8 @@
 static AccessibleEventListener* defunctnessListener;
 static AccessibleDeviceListener* mouseListener;
 static AccessibleEventListener* modifierListener;
+static AccessibleEventListener* windowActivateListener;
+static AccessibleEventListener* windowDeactivateListener;
 static gboolean m_gokSpyOpen = FALSE;
 static gint explicitrefs;
 static gint explicitunrefs;
@@ -159,9 +167,7 @@
 	if (accessible != NULL)
 	{
 		implicitrefs++;
-		gok_log("1");
 		s = Accessible_getName (accessible);
-		gok_log("1");
 		if (s == NULL)
 		{
 			gok_log ("%#x", accessible);
@@ -277,11 +283,15 @@
 			gok_spy_mouse_listener, NULL);
 		modifierListener = SPI_createAccessibleEventListener (
 			gok_spy_modifier_listener, NULL);
+		windowActivateListener = SPI_createAccessibleEventListener (
+			gok_spy_window_activate_listener, NULL);
+		windowDeactivateListener = SPI_createAccessibleEventListener (
+			gok_spy_window_deactivate_listener, NULL);
 
 		success = SPI_registerGlobalEventListener (focusListener, "focus:"); 
 		gok_log ("SPI_registerGlobalEventListener for focus events returned: %d" , success);
-		success = SPI_registerGlobalEventListener (defunctnessListener, "object:state-changed:defunct");
-		gok_log ("SPI_registerGlobalEventListener for defunct state events returned: %d" , success);
+		/* success = SPI_registerGlobalEventListener (defunctnessListener, "object:state-changed:defunct");
+		gok_log ("SPI_registerGlobalEventListener for defunct state events returned: %d" , success); */
 		success = SPI_registerDeviceEventListener (mouseListener,
 			SPI_BUTTON_PRESSED | SPI_BUTTON_RELEASED, NULL);
 		gok_log ("SPI_registerDeviceEventListener for mouse events returned: %d" , success);
@@ -290,6 +300,14 @@
 			"keyboard:modifiers");
 		gok_log ("SPI_registerGlobalEventListener for keyboard modifiers returned: %d", success);
 
+		success = SPI_registerGlobalEventListener (
+			windowActivateListener, "window:activate");
+		gok_log ("SPI_registerGlobalEventListener for window:activate returned: %d", success);
+
+		success = SPI_registerGlobalEventListener (
+			windowDeactivateListener, "window:deactivate");
+		gok_log ("SPI_registerGlobalEventListener for window:deactivate returned: %d", success);
+
 	}
 	gok_log_leave ();
 }
@@ -349,7 +367,7 @@
 		gok_log("eventQueue->length = %d", eventQueue->length);
 
 		/* iterate over event queue and dereference accessibles */
-		if (g_queue_is_empty(eventQueue) == FALSE)
+		while (g_queue_is_empty(eventQueue) == FALSE)
 		{
 			en = (EventNode*)g_queue_pop_head(eventQueue);
 			switch (en->type)
@@ -366,7 +384,7 @@
 			g_free(en);
 		}
 		g_queue_free(eventQueue);
-		
+
 	}
 	
 	gok_log_leave ();
@@ -546,25 +564,74 @@
 void gok_spy_check_queues(void)
 {
 	EventNode* en = NULL;
+	char *s;
+
 	gok_log_enter();
-	if (g_queue_is_empty(eventQueue) == FALSE)
+	while (g_queue_is_empty(eventQueue) == FALSE)
 	{
 		en = (EventNode*)g_queue_pop_head(eventQueue);
+
+		gok_log ("eventQueue->length = %d", eventQueue->length);
+
+		if (en->paccessible != NULL)
+		{
+			s = Accessible_getName (en->paccessible);
+			if (s == NULL)
+			{
+				gok_log ("%#x", en->paccessible);
+			}
+			else
+			{
+				gok_log ("%#x %s", en->paccessible, s);
+				SPI_freeString (s);
+			}
+		}
+
 		switch (en->type)
 		{
 		case GOKSPY_FOCUS_EVENT:
+			gok_log("GOKSPY_FOCUS_EVENT");
 			gok_spy_process_accessible(en->paccessible);
-			gok_log("dereferencing accessible from queue");
-			gok_spy_accessible_unref(en->paccessible);
 			break;
 		case GOKSPY_DEFUNCT_EVENT:
+			gok_log("GOKSPY_DEFUNCT_EVENT");
+			gok_spy_accessible_unref (m_ptheWindowAccessible);
 			m_ptheWindowAccessible = NULL;
 			((AppChangeListenerCB)(m_ptheWindowChangeListener))(m_ptheWindowAccessible);
 			break;
+		case GOKSPY_WINDOW_ACTIVATE_EVENT:
+			gok_log("GOKSPY_WINDOW_ACTIVATE_EVENT");
+			gok_spy_accessible_unref (m_ptheWindowAccessible);
+			m_ptheWindowAccessible = en->paccessible;
+			gok_spy_accessible_ref (m_ptheWindowAccessible);
+			((AppChangeListenerCB)(m_ptheWindowChangeListener))(m_ptheWindowAccessible);
+			break;
+		case GOKSPY_WINDOW_DEACTIVATE_EVENT:
+			gok_log("GOKSPY_WINDOW_DEACTIVATE_EVENT");
+
+			/* TODO: Determine if this workaround is necessary
+			 *       or if at-spi should be modified to
+			 *       not send out of order activate/deactivate
+			 *       events
+			 *
+			 * The test below is needed to workaround the case
+			 * that a window:deactivate event may arrive
+			 * after a window:activate has been emitted by
+			 * another window. The test ignores window:deactivate
+			 * events unless they come from what gok thinks
+			 * is the current window.
+			 */
+			if (en->paccessible == m_ptheWindowAccessible) {
+				gok_spy_accessible_unref (m_ptheWindowAccessible);
+				m_ptheWindowAccessible = NULL;
+				((AppChangeListenerCB)(m_ptheWindowChangeListener))(m_ptheWindowAccessible);
+			}
+			break;
 		default:
 			gok_log_x("unknown event type in internal gok event queue!");
 			break;
 		}
+		gok_spy_accessible_unref (en->paccessible);
 		g_free(en);
 	}
 	gok_log_leave();
@@ -894,6 +961,40 @@
     gok_log_leave();
 }
 
+static void
+gok_spy_window_activate_listener(const AccessibleEvent *event,
+                                 void *user_data)
+{
+	EventNode *en;
+	gok_log_enter ();
+
+	gok_spy_accessible_ref (event->source);
+	en = (EventNode*)g_malloc (sizeof (EventNode));
+	en->paccessible = event->source;
+	en->type = GOKSPY_WINDOW_ACTIVATE_EVENT;
+	g_queue_push_tail (eventQueue, en);
+	gok_spy_add_idle_handler ();
+
+	gok_log_leave ();
+}
+
+static void
+gok_spy_window_deactivate_listener(const AccessibleEvent *event,
+                                   void *user_data)
+{
+	EventNode *en;
+	gok_log_enter ();
+
+	gok_spy_accessible_ref (event->source);
+	en = (EventNode*)g_malloc (sizeof (EventNode));
+	en->paccessible = event->source;
+	en->type = GOKSPY_WINDOW_DEACTIVATE_EVENT;
+	g_queue_push_tail (eventQueue, en);
+	gok_spy_add_idle_handler ();
+
+	gok_log_leave ();
+}
+
 /** 
 * gok_spy_process_accessible 
 * 
@@ -955,10 +1056,13 @@
 	/*
 	 *  find the container for the focussed accessible thing 
 	 */
+	/*
 	gok_log("Looking for container...");
 	gok_log("accessible [%d]",accessible);
 	pnewWindowAccessible = accessible;
-	while (gok_spy_check_window(Accessible_getRole(pnewWindowAccessible)) != TRUE) /*|| (ptempAccessible != NULL))*/
+	while (gok_spy_check_window(Accessible_getRole(pnewWindowAccessible)) != TRUE)
+	*/ /*|| (ptempAccessible != NULL))*/
+	/*
 	{
 		gok_log("*");
     	ptempAccessible = Accessible_getParent(pnewWindowAccessible);
@@ -970,10 +1074,12 @@
     	gok_spy_accessible_unref(pnewWindowAccessible);
    	 pnewWindowAccessible = ptempAccessible;
     }
+	*/
 	 
 	/*
      * check to see if we have a new window 
 	 */
+	/*
 	gok_log("Comparing this container with existing...");
     if (pnewWindowAccessible != m_ptheWindowAccessible)
     {
@@ -985,10 +1091,12 @@
 	else
 	{
     	gok_log("same.");
+	*/
 		/* we have one ref too many (this isn't a different window) */
+	/*
 		gok_spy_accessible_unref(pnewWindowAccessible);
 	}
-
+	*/
 	gok_log_leave();
 } 
 
@@ -1093,7 +1201,6 @@
 	gok_log_leave();
 }
 
-
 static gboolean
 gok_spy_idle_handler (gpointer data)
 {
@@ -1251,5 +1358,4 @@
 	return plist;
 }
 */
-
 
