Performance improvement in getting accessible active window.
authorTomasz Olszak <t.olszak@samsung.com>
Mon, 3 Aug 2015 13:42:28 +0000 (15:42 +0200)
committerLukasz Stanislawski <l.stanislaws@samsung.com>
Tue, 4 Aug 2015 11:21:19 +0000 (20:21 +0900)
First we try to deteremine PID of currently active app using
ecore_x_window_focus_get. Then we iterate over accessible child apps
filtering by that app pid. If something goes wrong we fall back to previous
algorithm. Additionally some memory management fixes were added.
This improvement is proposed because iterating over accessible app windows
when app is not active is very time consuming (non active aps have low priority
and every dbus call takes a few hundred ms).

Change-Id: Ia18401200afa2bbc5f06e511f440f0fb51b16cd4

src/window_tracker.c

index 0016c8f..0630a72 100644 (file)
@@ -21,6 +21,9 @@
 #include <string.h>
 #include "window_tracker.h"
 #include "logger.h"
+#include <Ecore_X.h>
+#include <Ecore_X_Atoms.h>
+
 
 static Window_Tracker_Cb user_cb;
 static void *user_data;
@@ -45,32 +48,65 @@ static AtspiAccessible*
 _get_active_win(void)
 {
    DEBUG("START");
-   int i, j;
+   int i, j, desktop_children_count, app_children_count;
    last_active_win = NULL;
    AtspiAccessible *desktop = atspi_get_desktop(0);
    if (!desktop)
-      ERROR("DESKTOP NOT FOUND");
+     {
+        ERROR("DESKTOP NOT FOUND");
+        return NULL;
+     }
 
-   for (i = 0; i < atspi_accessible_get_child_count(desktop, NULL); i++)
+   Ecore_X_Window focus_window = ecore_x_window_focus_get();
+   unsigned int active_window_pid = 0;
+   if (focus_window)
+     {
+       //invoking atspi_accessible_get_child_count for non active apps results in very long screen-reader startup
+       //not active apps have low priority and dbus calls take a lot of time (a few hundred ms per call)
+       //Hence we first try to determine accessible window using pid of currently focused window
+       if (!ecore_x_window_prop_card32_get(focus_window, ECORE_X_ATOM_NET_WM_PID, &active_window_pid, 1))
+         active_window_pid = 0;
+       if (active_window_pid)
+         DEBUG("First we will try filter apps by PID: %i", active_window_pid);
+     }
+   desktop_children_count = atspi_accessible_get_child_count(desktop, NULL);
+   for (i = 0; i < desktop_children_count; i++)
       {
          AtspiAccessible *app = atspi_accessible_get_child_at_index(desktop, i, NULL);
-         for (j = 0; j < atspi_accessible_get_child_count(app, NULL); j++)
+
+         if (active_window_pid == 0 || active_window_pid == atspi_accessible_get_process_id(app, NULL))
+             app_children_count = atspi_accessible_get_child_count(app, NULL);
+         else
+             app_children_count = 0;
+
+         for (j = 0; j < app_children_count; j++)
             {
                AtspiAccessible *win = atspi_accessible_get_child_at_index(app, j, NULL);
                AtspiStateSet *states = atspi_accessible_get_state_set(win);
                AtspiRole role = atspi_accessible_get_role(win, NULL);
-
                if ((atspi_state_set_contains(states, ATSPI_STATE_ACTIVE)) && (role == ATSPI_ROLE_WINDOW))
-                  {
-                     g_object_unref(states);
-                     last_active_win = win;
-                     DEBUG("END");
-                     return last_active_win;
-                  }
+                  last_active_win = win;
+
+               g_object_unref(states);
+               g_object_unref(win);
+
+               if (last_active_win)
+                   break;
             }
+         g_object_unref(app);
+         if (active_window_pid > 0 && (i == desktop_children_count - 1))
+           {
+              // we are in last iteration and we should fall back to normal iteration over child windows
+              // without filtering by focus windows PID
+              i = -1;
+              active_window_pid = 0;
+           }
+         if (last_active_win)
+             break;
       }
-   ERROR("END");
-   return NULL;
+   g_object_unref(desktop);
+   DEBUG("END last_active_win: %p", last_active_win);
+   return last_active_win;
 }
 
 void window_tracker_init(void)