#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;
_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)