WindowTrackerCb user_cb;
void *user_data; // App_Tracker_Data *
AtspiEventListener *listener;
- AtspiAccessible *last_active_win;
AtspiAccessible *top_win;
Eina_List *window_infos;
AtspiAccessible *keyboard_window;
gchar *id = atspi_accessible_get_unique_id(wi->window, NULL);
AtspiRect extents;
if (_window_extents_get(wi->window, &extents)) {
- DEBUG("Window: %s (%d, %d, %d, %d) view change need: %d, keyboard window: %d",
+ DEBUG("Window: %s (%d, %d, %d, %d) view change need: %d, keyboard window: %d, is_focused: %d",
id, extents.x, extents.y, extents.width, extents.height,
- wi->view_change_need, wi->keyboard_window_is);
+ wi->view_change_need, wi->keyboard_window_is, wi->is_focused);
} else {
- DEBUG("Window: %s (no extents available) view change need: %d, keyboard window: %d",
- id, wi->view_change_need, wi->keyboard_window_is);
+ DEBUG("Window: %s (no extents available) view change need: %d, keyboard window: %d, is_focused: %d",
+ id, wi->view_change_need, wi->keyboard_window_is, wi->is_focused);
}
g_free(id);
}
}
static void _window_append(WindowTrackerData *wtd, AtspiAccessible *window, Eina_Bool view_change_need,
- Eina_Bool keyboard_window_is, WindowActivateInfoType window_activate_info_type)
+ Eina_Bool keyboard_window_is, WindowActivateInfoType window_activate_info_type, Eina_Bool is_focused)
{
// Increase reference count immediately to guard against g_object_unref() in the loop below.
// This is a danger only if 'window == wi->window', which is a stricter condition than
wi->view_change_need = view_change_need;
wi->window_activate_info_type = window_activate_info_type;
wi->resource_id = _window_resource_id_get(window);
+ wi->is_focused = is_focused;
wtd->window_infos = eina_list_append(wtd->window_infos, wi);
- if (view_change_need && wtd->user_cb)
- wtd->user_cb(wtd->user_data, window);
-
gchar *id = atspi_accessible_get_unique_id(window, NULL);
DEBUG("Window appended: %s", id);
g_free(id);
_window_stack_print(wtd);
}
-static AtspiAccessible *_top_window_get(WindowTrackerData *wtd)
+static AtspiAccessible *_top_focused_window_get(WindowTrackerData *wtd, Eina_Bool include_keyboard)
{
WindowInfo *wi = NULL;
+ Eina_List *l;
+ EINA_LIST_REVERSE_FOREACH(wtd->window_infos, l, wi) {
+ if (!wi) continue;
+ if (wi->is_focused && (include_keyboard || !wi->keyboard_window_is)) {
+ return wi->window;
+ }
+ }
+
+ return NULL;
+}
+
+static AtspiAccessible *_top_window_get(WindowTrackerData *wtd, Eina_Bool include_keyboard)
+{
_purge_windows_list(wtd);
- wi = eina_list_last_data_get(wtd->window_infos);
- if (wi)
- return wi->window;
+
+ AtspiAccessible *top = _top_focused_window_get(wtd, include_keyboard);
+ if(top)
+ return top;
+
+ DEBUG("No focused window found. Try finding last window from the stack.");
+ WindowInfo *wi = NULL;
+ Eina_List *l;
+ EINA_LIST_REVERSE_FOREACH(wtd->window_infos, l, wi) {
+ if (!wi) continue;
+ if (include_keyboard || !wi->keyboard_window_is) {
+ return wi->window;
+ }
+ }
return NULL;
}
+static void _switch_context_to_non_keyboard_top(WindowTrackerData *wtd)
+{
+ AtspiAccessible *top_window = _top_window_get(wtd, EINA_TRUE);
+ if (top_window) {
+ // If current top is keyboard window, use next top
+ if (atspi_accessible_is_equal(top_window, wtd->keyboard_window)) {
+ top_window = _top_window_get(wtd, EINA_FALSE);
+ }
+
+ wtd->user_cb(wtd->user_data, top_window);
+ gchar *id = atspi_accessible_get_unique_id(top_window, NULL);
+ DEBUG("top window: %s", id);
+ g_free(id);
+ } else {
+ app_tracker_null_context_switch(wtd->user_data);
+ }
+}
+
static void _window_remove(WindowTrackerData *wtd, AtspiAccessible *window)
{
Eina_Bool remove_from_top = EINA_FALSE;
AtspiAccessible *top_window;
- top_window = _top_window_get(wtd);
+ top_window = _top_window_get(wtd, EINA_FALSE);
remove_from_top = atspi_accessible_is_equal(top_window, window);
Eina_Bool window_removed = EINA_FALSE;
/* keyboard_window_is would be always FASLE because the
window_tracker_keyboard_window_remove does not use this function */
if (wtd->user_cb && !keyboard_window_is) {
- top_window = _top_window_get(wtd);
- if (top_window) {
- /* The current top could be keypad window,
- if so, use the second top window */
- wi = eina_list_last_data_get(wtd->window_infos);
- if (wi->keyboard_window_is) {
- int count = eina_list_count(wtd->window_infos);
- wi = eina_list_nth(wtd->window_infos, count - 2);
- if (wi)
- top_window = wi->window;
- else
- top_window = NULL;
- }
- if (top_window)
- wtd->user_cb(wtd->user_data, top_window);
- }
-
- if (!top_window)
- app_tracker_null_context_switch(wtd->user_data);
-
- gchar *id = atspi_accessible_get_unique_id(top_window, NULL);
- DEBUG("top window: %s", id);
- g_free(id);
+ _switch_context_to_non_keyboard_top(wtd);
}
} else {
/* The removed window could be under the keyboard window,
_window_stack_print(wtd);
}
+static void _active_window_set(WindowTrackerData *wtd, AtspiAccessible *window, Eina_Bool is_active)
+{
+ WindowInfo *wi;
+ Eina_List *l;
+ EINA_LIST_REVERSE_FOREACH(wtd->window_infos, l, wi) {
+ if (!wi) continue;
+ if (atspi_accessible_is_equal(wi->window, window)) {
+ wi->is_focused = is_active;
+ break;
+ }
+ }
+
+ if (wtd->user_cb) {
+ if (is_active)
+ wtd->user_cb(wtd->user_data, window);
+ else
+ _switch_context_to_non_keyboard_top(wtd);
+ }
+
+ gchar *id = atspi_accessible_get_unique_id(window, NULL);
+ DEBUG("active window set: %s[%d]", id, is_active);
+ g_free(id);
+ _window_stack_print(wtd);
+}
+
static void _on_atspi_window_cb(AtspiEvent *event, void *user_data)
{
WindowTrackerData *wtd = user_data;
window_tracker_keyboard_window_append(wtd);
goto end;
}
- _window_append(wtd, event->source, EINA_TRUE, EINA_FALSE, window_activate_info_type);
+ _window_append(wtd, event->source, EINA_TRUE, EINA_FALSE, window_activate_info_type, EINA_TRUE);
+ _active_window_set(wtd, event->source, EINA_TRUE);
+ } else if (!g_strcmp0(event->type, "window:deactivate")) {
+ _active_window_set(wtd, event->source, EINA_FALSE);
} else if (!g_strcmp0(event->type, "window:destroy")) {
DEBUG("Remove Window");
_window_remove(wtd, event->source);
if (event->detail1) { /* Visible */
if (role == ATSPI_ROLE_WINDOW || keyboard_is) {
DEBUG("Append %sWindow", keyboard_is ? "Keyboard " : "");
- _window_append(wtd, event->source, !keyboard_is, keyboard_is, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED);
+ _window_append(wtd, event->source, !keyboard_is, keyboard_is, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED, EINA_TRUE);
}
} else { /* Invisible */
if (role == ATSPI_ROLE_WINDOW || keyboard_is) {
AtspiRole role = atspi_accessible_get_role(event->source, NULL);
if (role == ATSPI_ROLE_FRAME) {
if (event->detail1)
- _window_append(wtd, event->source, EINA_TRUE, EINA_FALSE, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED);
+ _window_append(wtd, event->source, EINA_TRUE, EINA_FALSE, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED, EINA_TRUE);
else
_window_remove(wtd, event->source);
}
DEBUG("START");
AtspiAccessible *activeWindow = atspi_get_active_window();
if (activeWindow) {
- //TODO: probably need to use other condition
- DEBUG("active window: %p", activeWindow);
- _window_append(wtd, activeWindow, EINA_TRUE, EINA_FALSE, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED);
+ _active_window_set(wtd, activeWindow, EINA_TRUE);
g_object_unref(activeWindow);
}
}
DBUS_TYPE_STRING, &old,
DBUS_TYPE_STRING, &new,
DBUS_TYPE_INVALID)) {
- if (*old != '\0' && *new == '\0') {
+ if (*old != '\0' && *new == '\0' && !g_strcmp0(old, name)) {
_remove_window_under_bus(wtd, old);
}
}
_name_owner_changed_listener_register(wtd);
- wtd->last_active_win = NULL;
wtd->top_win = NULL;
wtd->window_infos = NULL;
wtd->keyboard_window = NULL;
DEBUG("Foreground windows: %d", windows->len);
for (i = 0; i < windows->len; i++) {
window = g_array_index(windows, AtspiAccessible *, i);
- _window_append(wtd, window, EINA_TRUE, EINA_FALSE, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED);
+ _window_append(wtd, window, EINA_TRUE, EINA_FALSE, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED, EINA_FALSE);
}
for (i = 0; i< windows->len; ++i) {
g_object_unref(g_array_index(windows, AtspiAccessible*, i));
return eina_list_last_data_get(wtd->window_infos);
}
-AtspiAccessible *window_tracker_top_window_get(WindowTrackerData *wtd)
+AtspiAccessible *window_tracker_top_window_get(WindowTrackerData *wtd, Eina_Bool include_keyboard)
{
- return _top_window_get(wtd);
+ return _top_window_get(wtd, include_keyboard);
}
-void window_tracker_window_append(WindowTrackerData *wtd, AtspiAccessible *window)
+void window_tracker_window_append(WindowTrackerData *wtd, AtspiAccessible *window, Eina_Bool is_focused)
{
if (atspi_accessible_is_equal(wtd->keyboard_window, window)) {
window_tracker_keyboard_window_append(wtd);
return;
}
- _window_append(wtd, window, EINA_TRUE, EINA_FALSE, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED);
+ _window_append(wtd, window, EINA_TRUE, EINA_FALSE, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED, is_focused);
+
+ // is_focused is true when this is called from focus_widget. Hence, we should switch focus to the given window.
+ if (is_focused)
+ _active_window_set(wtd, window, EINA_TRUE);
}
void window_tracker_window_remove(WindowTrackerData *wtd, AtspiAccessible *window)
void window_tracker_keyboard_window_append(WindowTrackerData *wtd)
{
- _window_append(wtd, wtd->keyboard_window, FALSE, EINA_TRUE, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED);
+ _window_append(wtd, wtd->keyboard_window, FALSE, EINA_TRUE, ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED, EINA_TRUE);
}
WindowActivateInfoType window_tracker_window_activate_info_type_get(WindowTrackerData *wtd, AtspiAccessible *window)