From c71956a578d72d7537a172bb8503c3ff7fe71e22 Mon Sep 17 00:00:00 2001 From: ksamak Date: Tue, 2 May 2017 11:09:03 +0200 Subject: [PATCH 01/20] focuspoll: WIP kixcaret functions and recurseFindText --- .../accessibilitywatcher.h | 4 + .../focuspoll/src/accessibilitywatcher.cpp | 151 +++++++++++++++++- 2 files changed, 153 insertions(+), 2 deletions(-) diff --git a/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h b/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h index a81489d0b..419f102e4 100644 --- a/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h +++ b/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h @@ -72,6 +72,10 @@ class AccessibilityWatcher { static void register_event(const AtspiEvent *event, std::string type); static bool app_specific_filter(FocusInfo& focus_info, const AtspiEvent* event); static bool filter_bad_events(const FocusInfo& event); + static bool getKixCaret (FocusInfo&, const AtspiEvent*); + static AtspiAccessible* recurseFindText(AtspiAccessible*); + static AtspiAccessible* recurseFindCursor(AtspiAccessible*); + static void print_attribute(gpointer key, gpointer value, gpointer userdata); static void get_alternative_caret(FocusInfo& focus, const AtspiEvent* event); static void on_focus(const AtspiEvent *event, void *data); diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index 4de21f121..b3d25cd3e 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -287,12 +287,26 @@ bool AccessibilityWatcher::app_specific_filter(FocusInfo& focus, const AtspiEven if (focus.type == "focus" && focus.role == "document frame") { // general page parasite event return true; } - if (focus.type == "caret" && !(focus.x == 0 && focus.y == 0)) { + if (focus.type == "caret" && + !(focus.x == 0 && focus.y == 0) && + !(focus.x < -2000 || focus.y < -2000)) { AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); return true; } + if (AccessibilityWatcher::getKixCaret(focus, event))// TODO DISCRIMINATE + { + AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); + std::cout << "manually added google document caret" << std::endl; + return true; + } + get_alternative_caret(focus, event); - if (focus.type == "caret" && !(focus.x_alt == 0 && focus.y_alt == 0)) { + std::cout << "alt caret tried" << std::endl; + if (focus.type == "caret" && + !(focus.x_alt == 0 && focus.y_alt == 0) && + !(focus.x_alt < -2000 || focus.y_alt < -2000) // TODO make define + ) { + std::cout << "alt focus is non 0" << std::endl; focus.x = focus.x_alt; focus.y = focus.y_alt + focus.h_alt; focus.w = focus.w_alt; @@ -340,6 +354,139 @@ bool AccessibilityWatcher::return_to_prev_menu() { return false; } +bool +AccessibilityWatcher::getKixCaret (FocusInfo& focus, const AtspiEvent* event) +{ + //Following a retro-engineered path to quicken cursor research + //accersiser path notation to usual location: 6 0 1 4 0 1 0; + auto target = atspi_accessible_get_parent(atspi_accessible_get_parent(atspi_accessible_get_parent(event->source, NULL), NULL), NULL); + //auto target = atspi_accessible_get_parent(event->source, NULL); + //target = atspi_accessible_get_child_at_index(target, 6, NULL); + //target = atspi_accessible_get_child_at_index(target, 0, NULL); + //target = atspi_accessible_get_child_at_index(target, 1, NULL); + //target = atspi_accessible_get_child_at_index(target, 4, NULL); + //target = atspi_accessible_get_child_at_index(target, 0, NULL); + //target = atspi_accessible_get_child_at_index(target, 1, NULL); + //target = atspi_accessible_get_child_at_index(target, 0, NULL); + + auto recursedCursor = recurseFindCursor(target); + if (recursedCursor) { + auto component = atspi_accessible_get_component(recursedCursor); + if (component) + { + AtspiRect* size = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + focus.x = size->x; + focus.y = size->y; + focus.w = size->width; + focus.h = size->height; + g_object_unref(component); + return true; + } + g_object_unref(component); + } + std::cout << "GCursor failed " << std::endl; + return false; + + //auto recursedAccessible = recurseFindText(target); + //auto component = atspi_accessible_get_component(recursedAccessible); + //if (component) + //{ + // AtspiRect* size = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + // std::cout << "component pos " << size->x << ":" << size->y << " size " << size->width << "x" << size->height << std::endl; + // g_object_unref(component); + //} else { + // std::cout << "component failed" << std::endl; + //} +} + +/* + * Recursively Finds a simulated kix cursor + */ +AtspiAccessible* +AccessibilityWatcher::recurseFindCursor(AtspiAccessible* accessible) +{ + auto attributes = atspi_accessible_get_attributes(accessible, NULL); + auto class_atr = g_hash_table_lookup(attributes, "class"); + if (class_atr) + { + //std::cout << "class attr: " << std::string((gchar*)class_atr) << std::endl; + if (std::string((gchar*)class_atr).find("kix-cursor-caret") != std::string::npos) + { + auto attributes = atspi_accessible_get_attributes(accessible, NULL); + g_hash_table_foreach(attributes, &print_attribute, NULL); + g_hash_table_destroy(attributes); + return accessible; + } + } + g_hash_table_destroy(attributes); + + auto childCount = atspi_accessible_get_child_count (accessible, NULL); + for (int i = 0; i < childCount; i++) { + auto res = recurseFindCursor(atspi_accessible_get_child_at_index(accessible, i, NULL)); + if (res) + { + std::cout << ",ch:" << i; + // auto offset = atspi_text_get_caret_offset(text, NULL); + // auto size = atspi_text_get_character_extents(text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); + // std::cout << " (" << size->x << "," << size->y << " " << size->width << "x" << size->height << ")" << std::endl; + return res; + } + } + return NULL; +} + +/* + * Recursively Finds text object in children of a given accessible + * returns the first text object with non-null content + */ +AtspiAccessible* +AccessibilityWatcher::recurseFindText(AtspiAccessible* accessible) +{ + auto text = atspi_accessible_get_text(accessible); + if (text) + { + auto attributes = atspi_accessible_get_attributes(accessible, NULL); + auto class_atr = g_hash_table_lookup(attributes, "class"); + //std::cout << "recursed text: " << atspi_text_get_text(text, 0, atspi_text_get_character_count(text, NULL), NULL) << std::endl; + if (atspi_text_get_character_count(text, NULL) > 0 + //&& strcmp(atspi_text_get_text(text, 0, atspi_text_get_character_count(text, NULL) - 1, NULL), "fuck") == 0 + //&& strcmp((gchar*)g_hash_table_lookup(attributes, "tag"), "span") == 0 + && class_atr + && strcmp((gchar*)class_atr, "goog-inline-block kix-lineview-text-block") == 0 + ) + { + std::cout << "found span text: " << atspi_text_get_text(text, 0, atspi_text_get_character_count(text, NULL) - 1, NULL) << std::endl; + auto offset = atspi_text_get_caret_offset(text, NULL); + auto size = atspi_text_get_character_extents(text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); + std::cout << " (" << size->x << "," << size->y << " " << size->width << "x" << size->height << ")" << std::endl; + + auto attributes = atspi_accessible_get_attributes(accessible, NULL); + g_hash_table_foreach(attributes, &print_attribute, NULL); + g_hash_table_destroy(attributes); + } + g_hash_table_destroy(attributes); + } + auto childCount = atspi_accessible_get_child_count (accessible, NULL); + for (int i = 0; i < childCount; i++) { + auto res = recurseFindText(atspi_accessible_get_child_at_index(accessible, i, NULL)); + if (res) + { +// std::cout << ",ch:" << i; +// auto offset = atspi_text_get_caret_offset(text, NULL); +// auto size = atspi_text_get_character_extents(text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); +// std::cout << " (" << size->x << "," << size->y << " " << size->width << "x" << size->height << ")" << std::endl; + return res; + } + } + return NULL; +} + +void AccessibilityWatcher::print_attribute(gpointer key, gpointer value, gpointer userdata) +{ + printf("attr %s : %s\n", (gchar*)key, (gchar*)value); +} + + void AccessibilityWatcher::get_alternative_caret(FocusInfo& focus, const AtspiEvent* event) { auto text = atspi_accessible_get_text(event->source); if (!text) { return; } -- GitLab From 58e3132ff26ade5d0364e201df375176faf9993a Mon Sep 17 00:00:00 2001 From: ksamak Date: Wed, 10 May 2017 13:52:42 +0200 Subject: [PATCH 02/20] focuspoll: more efficient, garbage collected kix funct. created getBrowserURL --- .../accessibilitywatcher.h | 3 +- .../focuspoll/src/accessibilitywatcher.cpp | 162 ++++++++---------- 2 files changed, 70 insertions(+), 95 deletions(-) diff --git a/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h b/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h index 419f102e4..04f296923 100644 --- a/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h +++ b/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h @@ -72,10 +72,9 @@ class AccessibilityWatcher { static void register_event(const AtspiEvent *event, std::string type); static bool app_specific_filter(FocusInfo& focus_info, const AtspiEvent* event); static bool filter_bad_events(const FocusInfo& event); + static std::string getBrowserURL(AtspiAccessible*); static bool getKixCaret (FocusInfo&, const AtspiEvent*); - static AtspiAccessible* recurseFindText(AtspiAccessible*); static AtspiAccessible* recurseFindCursor(AtspiAccessible*); - static void print_attribute(gpointer key, gpointer value, gpointer userdata); static void get_alternative_caret(FocusInfo& focus, const AtspiEvent* event); static void on_focus(const AtspiEvent *event, void *data); diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index b3d25cd3e..503f4393a 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -279,12 +279,14 @@ bool AccessibilityWatcher::app_specific_filter(FocusInfo& focus, const AtspiEven if (_ignore_links && focus.type != "caret" && focus.role == "link") { return true; } + // prevents status bar focus in firefox if (focus.type == "caret" && (static_cast(event->type) == "object:text-changed:insert:system" || - static_cast(event->type) == "object:text-changed:delete:system")) { // prevents status bar focus in firefox + static_cast(event->type) == "object:text-changed:delete:system")) { return true; } - if (focus.type == "focus" && focus.role == "document frame") { // general page parasite event + // general page parasite event + if (focus.type == "focus" && focus.role == "document frame") { return true; } if (focus.type == "caret" && @@ -293,20 +295,19 @@ bool AccessibilityWatcher::app_specific_filter(FocusInfo& focus, const AtspiEven AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); return true; } - if (AccessibilityWatcher::getKixCaret(focus, event))// TODO DISCRIMINATE + // assert whether we are inside a google document, then get kix caret + if (getBrowserURL(event->source).find("docs.google") != std::string::npos && + AccessibilityWatcher::getKixCaret(focus, event)) { AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); - std::cout << "manually added google document caret" << std::endl; return true; } get_alternative_caret(focus, event); - std::cout << "alt caret tried" << std::endl; if (focus.type == "caret" && !(focus.x_alt == 0 && focus.y_alt == 0) && !(focus.x_alt < -2000 || focus.y_alt < -2000) // TODO make define ) { - std::cout << "alt focus is non 0" << std::endl; focus.x = focus.x_alt; focus.y = focus.y_alt + focus.h_alt; focus.w = focus.w_alt; @@ -341,6 +342,36 @@ bool AccessibilityWatcher::filter_bad_events(const FocusInfo& event) { return false; } +std::string +AccessibilityWatcher::getBrowserURL(AtspiAccessible* accessible) +{ + if (!accessible) + return NULL; + + AtspiAccessible* parent = accessible; + while (parent != NULL) + { + auto document = atspi_accessible_get_document(parent); + auto nextParent = atspi_accessible_get_parent(parent, NULL); + g_object_unref(parent); + parent = nextParent; + if (!document) + continue; + + auto attributes = atspi_document_get_attributes(document, NULL); + if (!attributes) + continue; + + auto docURL = g_hash_table_lookup(attributes, "DocURL"); + if (docURL) + return std::string((gchar*)docURL); + + g_hash_table_destroy(attributes); + g_object_unref(document); + } + return NULL; +} + /* * this is meant to emulate the missing "selected" argument in menu hierarchy. * no idea whether this is a fail in GTK, or in ATSPI @@ -354,22 +385,38 @@ bool AccessibilityWatcher::return_to_prev_menu() { return false; } +/* + * Finds a kix online interative editor's caret (eg. in google docs) + * follows a retro-engineered path to accelerate cursor research + * accersiser path notation: 6 0 1 4 0 1 0; + */ bool AccessibilityWatcher::getKixCaret (FocusInfo& focus, const AtspiEvent* event) { - //Following a retro-engineered path to quicken cursor research - //accersiser path notation to usual location: 6 0 1 4 0 1 0; - auto target = atspi_accessible_get_parent(atspi_accessible_get_parent(atspi_accessible_get_parent(event->source, NULL), NULL), NULL); - //auto target = atspi_accessible_get_parent(event->source, NULL); - //target = atspi_accessible_get_child_at_index(target, 6, NULL); - //target = atspi_accessible_get_child_at_index(target, 0, NULL); - //target = atspi_accessible_get_child_at_index(target, 1, NULL); - //target = atspi_accessible_get_child_at_index(target, 4, NULL); - //target = atspi_accessible_get_child_at_index(target, 0, NULL); - //target = atspi_accessible_get_child_at_index(target, 1, NULL); - //target = atspi_accessible_get_child_at_index(target, 0, NULL); - + auto target = atspi_accessible_get_parent(event->source, NULL); + for (int i = 0; i < 2; ++i) + { + if (!target) + { + return false; + } + auto nextTarget = atspi_accessible_get_parent(target, NULL); + g_object_unref(target); + target = nextTarget; + } + std::vector path {6, 0, 1, 4, 0, 1}; + for (auto childNb : path) + { + if (!target) + { + return false; + } + auto nextTarget = atspi_accessible_get_child_at_index(target, childNb, NULL); + g_object_unref(target); + target = nextTarget; + } auto recursedCursor = recurseFindCursor(target); + g_object_unref(target); if (recursedCursor) { auto component = atspi_accessible_get_component(recursedCursor); if (component) @@ -384,19 +431,7 @@ AccessibilityWatcher::getKixCaret (FocusInfo& focus, const AtspiEvent* event) } g_object_unref(component); } - std::cout << "GCursor failed " << std::endl; return false; - - //auto recursedAccessible = recurseFindText(target); - //auto component = atspi_accessible_get_component(recursedAccessible); - //if (component) - //{ - // AtspiRect* size = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); - // std::cout << "component pos " << size->x << ":" << size->y << " size " << size->width << "x" << size->height << std::endl; - // g_object_unref(component); - //} else { - // std::cout << "component failed" << std::endl; - //} } /* @@ -409,83 +444,24 @@ AccessibilityWatcher::recurseFindCursor(AtspiAccessible* accessible) auto class_atr = g_hash_table_lookup(attributes, "class"); if (class_atr) { - //std::cout << "class attr: " << std::string((gchar*)class_atr) << std::endl; if (std::string((gchar*)class_atr).find("kix-cursor-caret") != std::string::npos) { - auto attributes = atspi_accessible_get_attributes(accessible, NULL); - g_hash_table_foreach(attributes, &print_attribute, NULL); g_hash_table_destroy(attributes); return accessible; } } g_hash_table_destroy(attributes); - auto childCount = atspi_accessible_get_child_count (accessible, NULL); - for (int i = 0; i < childCount; i++) { - auto res = recurseFindCursor(atspi_accessible_get_child_at_index(accessible, i, NULL)); - if (res) + for (int i = 0; i < atspi_accessible_get_child_count (accessible, NULL); i++) { + auto match = recurseFindCursor(atspi_accessible_get_child_at_index(accessible, i, NULL)); + if (match) { - std::cout << ",ch:" << i; - // auto offset = atspi_text_get_caret_offset(text, NULL); - // auto size = atspi_text_get_character_extents(text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); - // std::cout << " (" << size->x << "," << size->y << " " << size->width << "x" << size->height << ")" << std::endl; - return res; + return match; } } return NULL; } -/* - * Recursively Finds text object in children of a given accessible - * returns the first text object with non-null content - */ -AtspiAccessible* -AccessibilityWatcher::recurseFindText(AtspiAccessible* accessible) -{ - auto text = atspi_accessible_get_text(accessible); - if (text) - { - auto attributes = atspi_accessible_get_attributes(accessible, NULL); - auto class_atr = g_hash_table_lookup(attributes, "class"); - //std::cout << "recursed text: " << atspi_text_get_text(text, 0, atspi_text_get_character_count(text, NULL), NULL) << std::endl; - if (atspi_text_get_character_count(text, NULL) > 0 - //&& strcmp(atspi_text_get_text(text, 0, atspi_text_get_character_count(text, NULL) - 1, NULL), "fuck") == 0 - //&& strcmp((gchar*)g_hash_table_lookup(attributes, "tag"), "span") == 0 - && class_atr - && strcmp((gchar*)class_atr, "goog-inline-block kix-lineview-text-block") == 0 - ) - { - std::cout << "found span text: " << atspi_text_get_text(text, 0, atspi_text_get_character_count(text, NULL) - 1, NULL) << std::endl; - auto offset = atspi_text_get_caret_offset(text, NULL); - auto size = atspi_text_get_character_extents(text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); - std::cout << " (" << size->x << "," << size->y << " " << size->width << "x" << size->height << ")" << std::endl; - - auto attributes = atspi_accessible_get_attributes(accessible, NULL); - g_hash_table_foreach(attributes, &print_attribute, NULL); - g_hash_table_destroy(attributes); - } - g_hash_table_destroy(attributes); - } - auto childCount = atspi_accessible_get_child_count (accessible, NULL); - for (int i = 0; i < childCount; i++) { - auto res = recurseFindText(atspi_accessible_get_child_at_index(accessible, i, NULL)); - if (res) - { -// std::cout << ",ch:" << i; -// auto offset = atspi_text_get_caret_offset(text, NULL); -// auto size = atspi_text_get_character_extents(text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); -// std::cout << " (" << size->x << "," << size->y << " " << size->width << "x" << size->height << ")" << std::endl; - return res; - } - } - return NULL; -} - -void AccessibilityWatcher::print_attribute(gpointer key, gpointer value, gpointer userdata) -{ - printf("attr %s : %s\n", (gchar*)key, (gchar*)value); -} - void AccessibilityWatcher::get_alternative_caret(FocusInfo& focus, const AtspiEvent* event) { auto text = atspi_accessible_get_text(event->source); -- GitLab From edf04ac71af6b4cd3c3270801633d87e905c2e4c Mon Sep 17 00:00:00 2001 From: ksamak Date: Mon, 15 May 2017 11:18:10 +0200 Subject: [PATCH 03/20] changed arbitrary figures to local screen size --- .../focuspoll/src/accessibilitywatcher.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index 503f4393a..9f7936051 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -304,17 +304,17 @@ bool AccessibilityWatcher::app_specific_filter(FocusInfo& focus, const AtspiEven } get_alternative_caret(focus, event); - if (focus.type == "caret" && + if (focus.type == "caret" && !(focus.x_alt == 0 && focus.y_alt == 0) && - !(focus.x_alt < -2000 || focus.y_alt < -2000) // TODO make define - ) { - focus.x = focus.x_alt; - focus.y = focus.y_alt + focus.h_alt; - focus.w = focus.w_alt; - focus.h = focus.h_alt; - AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); - return true; - } + !(focus.x_alt < AccessibilityWatcher::get_instance()->screenWidth * -1 || focus.y_alt < AccessibilityWatcher::get_instance()->screenHeight * -1) + ) { + focus.x = focus.x_alt; + focus.y = focus.y_alt + focus.h_alt; + focus.w = focus.w_alt; + focus.h = focus.h_alt; + AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); + return true; + } } if (focus.application == "evince" && focus.type == "state-changed:selected" && focus.role == "icon") { // LO-calc: avoid spam event from main edit line return true; // ignores the parasite event from evince icon -- GitLab From 66894e85dade9b835d6da83dcb585538049c35e7 Mon Sep 17 00:00:00 2001 From: ksamak Date: Tue, 16 May 2017 13:47:42 +0200 Subject: [PATCH 04/20] cleaned print_event func --- .../focuspoll/src/accessibilitywatcher.cpp | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index 9f7936051..6450fcc45 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -98,32 +98,6 @@ const gchar* AccessibilityWatcher::atspi_state_get_name (gint state) { return value->value_nick; } -void AccessibilityWatcher::print_event(const AtspiEvent *event) { - if (std::string(atspi_accessible_get_name(event->source, NULL)) == "Paragraph 0") { return; } - std::cout << "=> "; - std::cout << event->type; - print_event(event->source); -} - -void AccessibilityWatcher::print_event(AtspiAccessible *access) { - ; - std::cout << " | " << atspi_accessible_get_name(atspi_accessible_get_application (access, NULL), NULL); - std::cout << " | " << atspi_accessible_get_name(access, NULL); - std::cout << " | " << atspi_accessible_get_role_name (access, NULL); - - AtspiStateSet *state_set = atspi_accessible_get_state_set (access); - if (atspi_state_set_contains(state_set, ATSPI_STATE_FOCUSED)) { - std::cout << " => Focused"; - } - std::cout << std::endl; - - auto component = atspi_accessible_get_component(access); - if (component) { - AtspiRect* size = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); - std::cout << " pos " << size->x << ":" << size->y << " size " << size->width << "x" << size->height << std::endl; - } -} - void AccessibilityWatcher::register_event(const AtspiEvent *event, std::string type) { FocusInfo res; res.type = type; // registered from filter on calling event -- GitLab From 46ad4e94ec49af66268f552f2b92fac718a56aaf Mon Sep 17 00:00:00 2001 From: ksamak Date: Tue, 16 May 2017 14:01:34 +0200 Subject: [PATCH 05/20] coding style modif --- .../focuspoll/src/accessibilitywatcher.cpp | 251 +++++++++--------- 1 file changed, 126 insertions(+), 125 deletions(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index 6450fcc45..0f0773be0 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -29,21 +29,21 @@ AccessibilityWatcher* AccessibilityWatcher::_instance = NULL; bool AccessibilityWatcher::_ignore_links = false; -AccessibilityWatcher::AccessibilityWatcher() : - screenWidth(0), - screenHeight(0), - _initialized(false) +AccessibilityWatcher::AccessibilityWatcher () : + screenWidth (0), + screenHeight (0), + _initialized (false) { } -AccessibilityWatcher* AccessibilityWatcher::get_instance() { - if(_instance == NULL) { - _instance = new AccessibilityWatcher(); +AccessibilityWatcher* AccessibilityWatcher::get_instance () { + if (_instance == NULL) { + _instance = new AccessibilityWatcher (); } return _instance; } -std::string AccessibilityWatcher::get_label(AtspiAccessible *accessible) { +std::string AccessibilityWatcher::get_label (AtspiAccessible *accessible) { GArray *relations; AtspiRelation *relation; @@ -55,17 +55,17 @@ std::string AccessibilityWatcher::get_label(AtspiAccessible *accessible) { for (unsigned i = 0; i < relations->len; i++) { relation = g_array_index (relations, AtspiRelation*, i); if (atspi_relation_get_relation_type (relation) == ATSPI_RELATION_LABELLED_BY) { - return atspi_accessible_get_name(atspi_relation_get_target(relation, 0), NULL); + return atspi_accessible_get_name (atspi_relation_get_target (relation, 0), NULL); } } return ""; } -void AccessibilityWatcher::setIgnoreLinks(bool val) { +void AccessibilityWatcher::setIgnoreLinks (bool val) { _ignore_links = val; } -void AccessibilityWatcher::setScreenLimits(int x, int y) { +void AccessibilityWatcher::setScreenLimits (int x, int y) { screenWidth = x; screenHeight = y; } @@ -75,7 +75,7 @@ void AccessibilityWatcher::setScreenLimits(int x, int y) { * is a child of the object that receives the focus/selection, so we * need to search for it. */ -AtspiAccessible* AccessibilityWatcher::find_child_slider(AtspiAccessible *accessible) { +AtspiAccessible* AccessibilityWatcher::find_child_slider (AtspiAccessible *accessible) { AtspiAccessible *child = NULL; int i = 0; @@ -104,27 +104,27 @@ void AccessibilityWatcher::register_event(const AtspiEvent *event, std::string t res.name = atspi_accessible_get_name (event->source, NULL); res.label = get_label (event->source); res.role = atspi_accessible_get_role_name (event->source, NULL); - res.application = atspi_accessible_get_name(atspi_accessible_get_application (event->source, NULL), NULL); + res.application = atspi_accessible_get_name (atspi_accessible_get_application (event->source, NULL), NULL); - auto child = atspi_accessible_get_parent(event->source, NULL); + auto child = atspi_accessible_get_parent (event->source, NULL); while (!res.active && child) { // prevents events that are actually from an active child. weird behaviour. auto state_set = atspi_accessible_get_state_set (child); - if (atspi_state_set_contains(state_set, ATSPI_STATE_ACTIVE)) { + if (atspi_state_set_contains (state_set, ATSPI_STATE_ACTIVE)) { res.active = true; } - child = atspi_accessible_get_parent(child, NULL); + child = atspi_accessible_get_parent (child, NULL); } AtspiComponent* component; if (res.type == "active-descendant-changed") { - auto accessible = atspi_accessible_get_child_at_index(event->source, event->detail1, NULL); - component = atspi_accessible_get_component(accessible); + auto accessible = atspi_accessible_get_child_at_index (event->source, event->detail1, NULL); + component = atspi_accessible_get_component (accessible); } else { - component = atspi_accessible_get_component(event->source); + component = atspi_accessible_get_component (event->source); } if (component) { - AtspiRect* size = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + AtspiRect* size = atspi_component_get_extents (component, ATSPI_COORD_TYPE_SCREEN, NULL); res.x = size->x; res.y = size->y; res.w = size->width; @@ -132,40 +132,40 @@ void AccessibilityWatcher::register_event(const AtspiEvent *event, std::string t } // let's get the caret offset, and then its position for a caret event if (type == "caret") { - auto text = atspi_accessible_get_text(event->source); + auto text = atspi_accessible_get_text (event->source); if (!text) { return; } - auto offset = atspi_text_get_caret_offset(text, NULL); + auto offset = atspi_text_get_caret_offset (text, NULL); if (event->detail1) { // if we're at the beginning of text, let the widget pos decide TODO check that - AtspiRect *size = atspi_text_get_character_extents(text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); + AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); res.x = size->x; res.y = size->y; res.w = size->width; res.h = size->height; } if (res.x == 0 && res.y == 0 && offset > 0) { // correcting a missing offset to a caret move event in ff TODO file bug - AtspiRect *size = atspi_text_get_character_extents(text, offset-1, ATSPI_COORD_TYPE_SCREEN, NULL); + AtspiRect *size = atspi_text_get_character_extents (text, offset-1, ATSPI_COORD_TYPE_SCREEN, NULL); res.x = size->x; res.y = size->y; res.w = size->width; res.h = size->height; } - if (std::string(event->type) == "object:text-caret-moved" && (res.w > 50 || res.h > 70)) { // this is obviously not a caret size - AtspiRect *size = atspi_text_get_character_extents(text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); + if (std::string (event->type) == "object:text-caret-moved" && (res.w > 50 || res.h > 70)) { // this is obviously not a caret size + AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); res.x = size->x; res.y = size->y; res.w = size->width; res.h = size->height; - if (type == "caret" && std::string(event->type) == "object:text-caret-moved" && (res.w > 50 || res.h > 70)) { + if (type == "caret" && std::string (event->type) == "object:text-caret-moved" && (res.w > 50 || res.h > 70)) { res.x = 0; res.y = 0; } } if (res.x == 0 && res.y == 0 && // still no offset, it's probably a newline - (std::string(event->type) == "object:text-changed:insert" || - std::string(event->type) == "object:text-changed:removed" || - std::string(event->type) == "object:text-caret-moved")) { + (std::string (event->type) == "object:text-changed:insert" || + std::string (event->type) == "object:text-changed:removed" || + std::string (event->type) == "object:text-caret-moved")) { res.x = res.x_alt; res.y = res.y_alt; res.w = res.w_alt; @@ -175,31 +175,31 @@ void AccessibilityWatcher::register_event(const AtspiEvent *event, std::string t // getting the states on event auto state_set = atspi_accessible_get_state_set (event->source); - if (atspi_state_set_contains(state_set, ATSPI_STATE_FOCUSED)) { + if (atspi_state_set_contains (state_set, ATSPI_STATE_FOCUSED)) { res.focused = true; - AccessibilityWatcher::get_instance()->_previously_active_menus.clear(); // reset potential menu stack + AccessibilityWatcher::get_instance ()->_previously_active_menus.clear (); // reset potential menu stack } - if (atspi_state_set_contains(state_set, ATSPI_STATE_SELECTED)) { // never works, GTK Bad implem? + if (atspi_state_set_contains (state_set, ATSPI_STATE_SELECTED)) { // never works, GTK Bad implem? res.selected = true; } if (res.type == "state-changed:selected" && event->detail1 == 1) { res.selected = true; - AccessibilityWatcher::get_instance()->_previously_active_menus.push_back(res); // add to stack of menus + AccessibilityWatcher::get_instance ()->_previously_active_menus.push_back (res); // add to stack of menus } - if (app_specific_filter(res, event)) { + if (app_specific_filter (res, event)) { return; } - if (filter_bad_events(res)) { + if (filter_bad_events (res)) { return; } - while (AccessibilityWatcher::get_instance()->_focus_list.size() >= 5) { // don't keep the whole history - AccessibilityWatcher::get_instance()->_focus_list.erase(AccessibilityWatcher::get_instance()->_focus_list.begin()); + while (AccessibilityWatcher::get_instance ()->_focus_list.size () >= 5) { // don't keep the whole history + AccessibilityWatcher::get_instance ()->_focus_list.erase (AccessibilityWatcher::get_instance ()->_focus_list.begin ()); } - AccessibilityWatcher::get_instance()->_focus_list.push_back(res); + AccessibilityWatcher::get_instance ()->_focus_list.push_back (res); } -bool AccessibilityWatcher::app_specific_filter(FocusInfo& focus, const AtspiEvent* event) { +bool AccessibilityWatcher::app_specific_filter (FocusInfo& focus, const AtspiEvent* event) { if (focus.type == "state-changed:selected" && // emulates on-change:selected false behaviour. eg: for menus (focus.role == "menu item" || focus.role == "menu" || @@ -207,14 +207,14 @@ bool AccessibilityWatcher::app_specific_filter(FocusInfo& focus, const AtspiEven focus.role == "radio menu item") && focus.application != "mate-panel") { - if (!focus.selected && AccessibilityWatcher::get_instance()->return_to_prev_menu()) { + if (!focus.selected && AccessibilityWatcher::get_instance ()->return_to_prev_menu ()) { return true; } focus.active = true; } if (focus.application == "soffice" && focus.role == "paragraph") { // LO-calc: avoid spam event from main edit line - auto parent = atspi_accessible_get_parent(event->source, NULL); - std::string parent_label = atspi_accessible_get_name(parent, NULL); + auto parent = atspi_accessible_get_parent (event->source, NULL); + std::string parent_label = atspi_accessible_get_name (parent, NULL); if (parent_label == "Input line" || parent_label == "Ligne de saisie") { return true; @@ -222,29 +222,29 @@ bool AccessibilityWatcher::app_specific_filter(FocusInfo& focus, const AtspiEven } if (focus.application == "Icedove" || focus.application == "Thunderbird") { if (focus.type == "caret") { - auto text = atspi_accessible_get_text(event->source); // next if deals with a special newline char, that remained buggy. hypra issue #430 - auto offset = atspi_text_get_caret_offset(text, NULL); - auto string = std::string(atspi_text_get_text_at_offset(text, offset, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); - auto string_m1 = std::string(atspi_text_get_text_at_offset(text, offset -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); - if (offset == atspi_text_get_character_count(text, NULL) && string == "\0" && (string_m1 == "\n" || int(string_m1.c_str()[0]) == -17)) { - get_alternative_caret(focus, event); + auto text = atspi_accessible_get_text (event->source); // next if deals with a special newline char, that remained buggy. hypra issue #430 + auto offset = atspi_text_get_caret_offset (text, NULL); + auto string = std::string (atspi_text_get_text_at_offset (text, offset, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); + auto string_m1 = std::string (atspi_text_get_text_at_offset (text, offset -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); + if (offset == atspi_text_get_character_count (text, NULL) && string == "\0" && (string_m1 == "\n" || int (string_m1.c_str ()[0]) == -17)) { + get_alternative_caret (focus, event); focus.x = focus.x_alt; focus.y = focus.y_alt + focus.h_alt; focus.w = focus.w_alt; focus.h = focus.h_alt; } - if (!(focus.x == 0 && focus.y == 0)) { // prevents compose window loss of tracking in HTML mode (active flag ok, but no focused flag) - AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); + if (! (focus.x == 0 && focus.y == 0)) { // prevents compose window loss of tracking in HTML mode (active flag ok, but no focused flag) + AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); return true; } - auto component = atspi_accessible_get_component(event->source); + auto component = atspi_accessible_get_component (event->source); if (component) { - AtspiRect* size = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + AtspiRect* size = atspi_component_get_extents (component, ATSPI_COORD_TYPE_SCREEN, NULL); focus.x = size->x; focus.y = size->y; focus.w = 7; focus.h = size->height; - AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); + AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); return true; } } @@ -255,8 +255,8 @@ bool AccessibilityWatcher::app_specific_filter(FocusInfo& focus, const AtspiEven } // prevents status bar focus in firefox if (focus.type == "caret" && - (static_cast(event->type) == "object:text-changed:insert:system" || - static_cast(event->type) == "object:text-changed:delete:system")) { + (static_cast (event->type) == "object:text-changed:insert:system" || + static_cast (event->type) == "object:text-changed:delete:system")) { return true; } // general page parasite event @@ -266,27 +266,27 @@ bool AccessibilityWatcher::app_specific_filter(FocusInfo& focus, const AtspiEven if (focus.type == "caret" && !(focus.x == 0 && focus.y == 0) && !(focus.x < -2000 || focus.y < -2000)) { - AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); + AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); return true; } // assert whether we are inside a google document, then get kix caret - if (getBrowserURL(event->source).find("docs.google") != std::string::npos && - AccessibilityWatcher::getKixCaret(focus, event)) + if (getBrowserURL (event->source).find ("docs.google") != std::string::npos && + AccessibilityWatcher::getKixCaret (focus, event)) { - AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); + AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); return true; } - get_alternative_caret(focus, event); + get_alternative_caret (focus, event); if (focus.type == "caret" && !(focus.x_alt == 0 && focus.y_alt == 0) && - !(focus.x_alt < AccessibilityWatcher::get_instance()->screenWidth * -1 || focus.y_alt < AccessibilityWatcher::get_instance()->screenHeight * -1) + !(focus.x_alt < AccessibilityWatcher::get_instance ()->screenWidth * -1 || focus.y_alt < AccessibilityWatcher::get_instance ()->screenHeight * -1) ) { focus.x = focus.x_alt; focus.y = focus.y_alt + focus.h_alt; focus.w = focus.w_alt; focus.h = focus.h_alt; - AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); + AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); return true; } } @@ -296,7 +296,7 @@ bool AccessibilityWatcher::app_specific_filter(FocusInfo& focus, const AtspiEven return false; } -bool AccessibilityWatcher::filter_bad_events(const FocusInfo& event) { +bool AccessibilityWatcher::filter_bad_events (const FocusInfo& event) { if (event.type == "caret" && event.x ==0 && event.y == 0) { return true; } @@ -306,9 +306,9 @@ bool AccessibilityWatcher::filter_bad_events(const FocusInfo& event) { if (!event.focused && !event.selected) { return true; } - if (AccessibilityWatcher::get_instance()->screenWidth != 0 && AccessibilityWatcher::get_instance()->screenHeight !=0 && - (event.x > AccessibilityWatcher::get_instance()->screenWidth || - event.y > AccessibilityWatcher::get_instance()->screenHeight || // TODO remove when non-singleton + if (AccessibilityWatcher::get_instance ()->screenWidth != 0 && AccessibilityWatcher::get_instance ()->screenHeight !=0 && + (event.x > AccessibilityWatcher::get_instance ()->screenWidth || + event.y > AccessibilityWatcher::get_instance ()->screenHeight || // TODO remove when non-singleton event.x < 0 || event.y < 0 )) { return true; @@ -317,7 +317,7 @@ bool AccessibilityWatcher::filter_bad_events(const FocusInfo& event) { } std::string -AccessibilityWatcher::getBrowserURL(AtspiAccessible* accessible) +AccessibilityWatcher::getBrowserURL (AtspiAccessible* accessible) { if (!accessible) return NULL; @@ -325,35 +325,36 @@ AccessibilityWatcher::getBrowserURL(AtspiAccessible* accessible) AtspiAccessible* parent = accessible; while (parent != NULL) { - auto document = atspi_accessible_get_document(parent); - auto nextParent = atspi_accessible_get_parent(parent, NULL); - g_object_unref(parent); + auto document = atspi_accessible_get_document (parent); + auto nextParent = atspi_accessible_get_parent (parent, NULL); + g_object_unref (parent); parent = nextParent; if (!document) continue; - auto attributes = atspi_document_get_attributes(document, NULL); + auto attributes = atspi_document_get_attributes (document, NULL); if (!attributes) continue; - auto docURL = g_hash_table_lookup(attributes, "DocURL"); + auto docURL = g_hash_table_lookup (attributes, "DocURL"); if (docURL) - return std::string((gchar*)docURL); + return std::string ((gchar*)docURL); - g_hash_table_destroy(attributes); - g_object_unref(document); + g_hash_table_destroy (attributes); + g_object_unref (document); } return NULL; } + /* * this is meant to emulate the missing "selected" argument in menu hierarchy. * no idea whether this is a fail in GTK, or in ATSPI */ -bool AccessibilityWatcher::return_to_prev_menu() { - if (_previously_active_menus.size() > 1) { - _previously_active_menus.pop_back(); - _focus_list.push_back(_previously_active_menus.back()); +bool AccessibilityWatcher::return_to_prev_menu () { + if (_previously_active_menus.size () > 1) { + _previously_active_menus.pop_back (); + _focus_list.push_back (_previously_active_menus.back ()); return true; } return false; @@ -367,15 +368,15 @@ bool AccessibilityWatcher::return_to_prev_menu() { bool AccessibilityWatcher::getKixCaret (FocusInfo& focus, const AtspiEvent* event) { - auto target = atspi_accessible_get_parent(event->source, NULL); + auto target = atspi_accessible_get_parent (event->source, NULL); for (int i = 0; i < 2; ++i) { if (!target) { return false; } - auto nextTarget = atspi_accessible_get_parent(target, NULL); - g_object_unref(target); + auto nextTarget = atspi_accessible_get_parent (target, NULL); + g_object_unref (target); target = nextTarget; } std::vector path {6, 0, 1, 4, 0, 1}; @@ -385,25 +386,25 @@ AccessibilityWatcher::getKixCaret (FocusInfo& focus, const AtspiEvent* event) { return false; } - auto nextTarget = atspi_accessible_get_child_at_index(target, childNb, NULL); - g_object_unref(target); + auto nextTarget = atspi_accessible_get_child_at_index (target, childNb, NULL); + g_object_unref (target); target = nextTarget; } - auto recursedCursor = recurseFindCursor(target); - g_object_unref(target); + auto recursedCursor = recurseFindCursor (target); + g_object_unref (target); if (recursedCursor) { - auto component = atspi_accessible_get_component(recursedCursor); + auto component = atspi_accessible_get_component (recursedCursor); if (component) { - AtspiRect* size = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + AtspiRect* size = atspi_component_get_extents (component, ATSPI_COORD_TYPE_SCREEN, NULL); focus.x = size->x; focus.y = size->y; focus.w = size->width; focus.h = size->height; - g_object_unref(component); + g_object_unref (component); return true; } - g_object_unref(component); + g_object_unref (component); } return false; } @@ -412,22 +413,22 @@ AccessibilityWatcher::getKixCaret (FocusInfo& focus, const AtspiEvent* event) * Recursively Finds a simulated kix cursor */ AtspiAccessible* -AccessibilityWatcher::recurseFindCursor(AtspiAccessible* accessible) +AccessibilityWatcher::recurseFindCursor (AtspiAccessible* accessible) { - auto attributes = atspi_accessible_get_attributes(accessible, NULL); - auto class_atr = g_hash_table_lookup(attributes, "class"); + auto attributes = atspi_accessible_get_attributes (accessible, NULL); + auto class_atr = g_hash_table_lookup (attributes, "class"); if (class_atr) { - if (std::string((gchar*)class_atr).find("kix-cursor-caret") != std::string::npos) + if (std::string ((gchar*)class_atr).find ("kix-cursor-caret") != std::string::npos) { - g_hash_table_destroy(attributes); + g_hash_table_destroy (attributes); return accessible; } } - g_hash_table_destroy(attributes); + g_hash_table_destroy (attributes); for (int i = 0; i < atspi_accessible_get_child_count (accessible, NULL); i++) { - auto match = recurseFindCursor(atspi_accessible_get_child_at_index(accessible, i, NULL)); + auto match = recurseFindCursor (atspi_accessible_get_child_at_index (accessible, i, NULL)); if (match) { return match; @@ -437,34 +438,34 @@ AccessibilityWatcher::recurseFindCursor(AtspiAccessible* accessible) } -void AccessibilityWatcher::get_alternative_caret(FocusInfo& focus, const AtspiEvent* event) { - auto text = atspi_accessible_get_text(event->source); +void AccessibilityWatcher::get_alternative_caret (FocusInfo& focus, const AtspiEvent* event) { + auto text = atspi_accessible_get_text (event->source); if (!text) { return; } - auto offset = atspi_text_get_caret_offset(text, NULL); - auto caret_char = std::string(atspi_text_get_text_at_offset(text, offset, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); + auto offset = atspi_text_get_caret_offset (text, NULL); + auto caret_char = std::string (atspi_text_get_text_at_offset (text, offset, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); bool has_seen_17 = false; if (caret_char == "\n" || caret_char == "\0") { // if we're at a newline, sometimes ATSPI doesn't feel like giving us a caret position. int lines = 0; - if (atspi_text_get_character_count(text, NULL) == offset) { + if (atspi_text_get_character_count (text, NULL) == offset) { lines++; // gives the last empty line the right focus. } int it = 1; bool char_extents_found = false; - AtspiRect *size = atspi_text_get_character_extents(text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); + AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); while (!char_extents_found && it <= offset && it < 300) { // try and find the character on upper line to extrapolate from - size = atspi_text_get_character_extents(text, offset - it, ATSPI_COORD_TYPE_SCREEN, NULL); - caret_char = atspi_text_get_text_at_offset(text, offset -it, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content; - if ((size->x != 0 || size->y != 0) && int(caret_char[0]) != -17) { // if we found a caret, check we're at beginning of line (or of text) - if (offset -it -1 >= 0 && std::string(atspi_text_get_text_at_offset(text, offset -it -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content) == "\n") { + size = atspi_text_get_character_extents (text, offset - it, ATSPI_COORD_TYPE_SCREEN, NULL); + caret_char = atspi_text_get_text_at_offset (text, offset -it, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content; + if ((size->x != 0 || size->y != 0) && int (caret_char[0]) != -17) { // if we found a caret, check we're at beginning of line (or of text) + if (offset -it -1 >= 0 && std::string (atspi_text_get_text_at_offset (text, offset -it -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content) == "\n") { char_extents_found = true; // first character of upper line has been found } else if (offset -it -1 == 0) { - size = atspi_text_get_character_extents(text, 0, ATSPI_COORD_TYPE_SCREEN, NULL); + size = atspi_text_get_character_extents (text, 0, ATSPI_COORD_TYPE_SCREEN, NULL); char_extents_found = true; // first character of upper line has been found } - } else if (caret_char == "\n" || int(caret_char[0]) == -17) { + } else if (caret_char == "\n" || int (caret_char[0]) == -17) { lines ++; } - if (!has_seen_17 && int(caret_char[0]) == -17 ) { + if (!has_seen_17 && int (caret_char[0]) == -17 ) { has_seen_17 = true; } it ++; @@ -481,11 +482,11 @@ void AccessibilityWatcher::get_alternative_caret(FocusInfo& focus, const AtspiEv void AccessibilityWatcher::on_caret_move (const AtspiEvent *event, void *data) { - register_event(event, "caret"); + register_event (event, "caret"); } void AccessibilityWatcher::on_selected_change (const AtspiEvent *event, void *data) { - register_event(event, "state-changed:selected"); + register_event (event, "state-changed:selected"); } void AccessibilityWatcher::on_focus (const AtspiEvent *event, void *data) { @@ -493,15 +494,15 @@ void AccessibilityWatcher::on_focus (const AtspiEvent *event, void *data) { * there's no detail1 on focus loss in AT-SPI specs */ if (!event->detail1) {return;} - register_event(event, "focus"); + register_event (event, "focus"); } void AccessibilityWatcher::on_descendant_changed (const AtspiEvent *event, void *data) { - register_event(event, "active-descendant-changed"); + register_event (event, "active-descendant-changed"); } /* Register to events */ -void AccessibilityWatcher::addWatches() { +void AccessibilityWatcher::addWatches () { listener = atspi_event_listener_new ((AtspiEventListenerCB)on_focus, NULL, NULL); listener2 = atspi_event_listener_new ((AtspiEventListenerCB)on_caret_move, NULL, NULL); listener3 = atspi_event_listener_new ((AtspiEventListenerCB)on_selected_change, NULL, NULL); @@ -515,7 +516,7 @@ void AccessibilityWatcher::addWatches() { atspi_event_listener_register (listener4, "object:active-descendant-changed", NULL); } -void AccessibilityWatcher::removeWatches() { +void AccessibilityWatcher::removeWatches () { atspi_event_listener_deregister (listener, "object:state-changed:focused", NULL); atspi_event_listener_deregister (listener2, "object:text-caret-moved", NULL); atspi_event_listener_deregister (listener2, "object:text-changed:inserted", NULL); @@ -524,26 +525,26 @@ void AccessibilityWatcher::removeWatches() { atspi_event_listener_deregister (listener4, "object:active-descendant-changed", NULL); } -void AccessibilityWatcher::init() { +void AccessibilityWatcher::init () { if (_initialized) { return; } atspi_init (); - atspi_set_main_context(g_main_context_default()); - addWatches(); + atspi_set_main_context (g_main_context_default ()); + addWatches (); _initialized = true; } -void AccessibilityWatcher::quit() { - removeWatches(); +void AccessibilityWatcher::quit () { + removeWatches (); _initialized = false; } -std::deque AccessibilityWatcher::get_focus_queue() { +std::deque AccessibilityWatcher::get_focus_queue () { return _focus_list; } -void AccessibilityWatcher::reset_focus_queue() { - _focus_list.clear(); +void AccessibilityWatcher::reset_focus_queue () { + _focus_list.clear (); } -- GitLab From ecdb3a4986683312557e586e0d650920a9772fe3 Mon Sep 17 00:00:00 2001 From: ksamak Date: Tue, 16 May 2017 14:02:53 +0200 Subject: [PATCH 06/20] gnuCodingStyle --- .../focuspoll/src/accessibilitywatcher.cpp | 362 +++++++++--------- 1 file changed, 181 insertions(+), 181 deletions(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index 0f0773be0..27717bd1e 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -30,15 +30,15 @@ AccessibilityWatcher* AccessibilityWatcher::_instance = NULL; bool AccessibilityWatcher::_ignore_links = false; AccessibilityWatcher::AccessibilityWatcher () : - screenWidth (0), - screenHeight (0), - _initialized (false) + screenWidth (0), + screenHeight (0), + _initialized (false) { } AccessibilityWatcher* AccessibilityWatcher::get_instance () { if (_instance == NULL) { - _instance = new AccessibilityWatcher (); + _instance = new AccessibilityWatcher (); } return _instance; } @@ -49,14 +49,14 @@ std::string AccessibilityWatcher::get_label (AtspiAccessible *accessible) { relations = atspi_accessible_get_relation_set (accessible, NULL); if (relations == NULL) { - return ""; + return ""; } for (unsigned i = 0; i < relations->len; i++) { - relation = g_array_index (relations, AtspiRelation*, i); - if (atspi_relation_get_relation_type (relation) == ATSPI_RELATION_LABELLED_BY) { - return atspi_accessible_get_name (atspi_relation_get_target (relation, 0), NULL); - } + relation = g_array_index (relations, AtspiRelation*, i); + if (atspi_relation_get_relation_type (relation) == ATSPI_RELATION_LABELLED_BY) { + return atspi_accessible_get_name (atspi_relation_get_target (relation, 0), NULL); + } } return ""; } @@ -66,8 +66,8 @@ void AccessibilityWatcher::setIgnoreLinks (bool val) { } void AccessibilityWatcher::setScreenLimits (int x, int y) { - screenWidth = x; - screenHeight = y; + screenWidth = x; + screenHeight = y; } /* @@ -80,10 +80,10 @@ AtspiAccessible* AccessibilityWatcher::find_child_slider (AtspiAccessible *acces int i = 0; for (i = 0; i < atspi_accessible_get_child_count (accessible, NULL); i++) { - child = atspi_accessible_get_child_at_index (accessible, i, NULL); - if (atspi_accessible_get_role (child, NULL) == ATSPI_ROLE_SLIDER) { - break; - } + child = atspi_accessible_get_child_at_index (accessible, i, NULL); + if (atspi_accessible_get_role (child, NULL) == ATSPI_ROLE_SLIDER) { + break; + } } return child; @@ -108,176 +108,176 @@ void AccessibilityWatcher::register_event(const AtspiEvent *event, std::string t auto child = atspi_accessible_get_parent (event->source, NULL); while (!res.active && child) { // prevents events that are actually from an active child. weird behaviour. - auto state_set = atspi_accessible_get_state_set (child); - if (atspi_state_set_contains (state_set, ATSPI_STATE_ACTIVE)) { - res.active = true; - } - child = atspi_accessible_get_parent (child, NULL); + auto state_set = atspi_accessible_get_state_set (child); + if (atspi_state_set_contains (state_set, ATSPI_STATE_ACTIVE)) { + res.active = true; + } + child = atspi_accessible_get_parent (child, NULL); } AtspiComponent* component; if (res.type == "active-descendant-changed") { - auto accessible = atspi_accessible_get_child_at_index (event->source, event->detail1, NULL); - component = atspi_accessible_get_component (accessible); + auto accessible = atspi_accessible_get_child_at_index (event->source, event->detail1, NULL); + component = atspi_accessible_get_component (accessible); } else { - component = atspi_accessible_get_component (event->source); + component = atspi_accessible_get_component (event->source); } if (component) { - AtspiRect* size = atspi_component_get_extents (component, ATSPI_COORD_TYPE_SCREEN, NULL); - res.x = size->x; - res.y = size->y; - res.w = size->width; - res.h = size->height; + AtspiRect* size = atspi_component_get_extents (component, ATSPI_COORD_TYPE_SCREEN, NULL); + res.x = size->x; + res.y = size->y; + res.w = size->width; + res.h = size->height; } // let's get the caret offset, and then its position for a caret event if (type == "caret") { - auto text = atspi_accessible_get_text (event->source); - if (!text) { - return; - } - auto offset = atspi_text_get_caret_offset (text, NULL); - if (event->detail1) { // if we're at the beginning of text, let the widget pos decide TODO check that - AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); - res.x = size->x; - res.y = size->y; - res.w = size->width; - res.h = size->height; - } - if (res.x == 0 && res.y == 0 && offset > 0) { // correcting a missing offset to a caret move event in ff TODO file bug - AtspiRect *size = atspi_text_get_character_extents (text, offset-1, ATSPI_COORD_TYPE_SCREEN, NULL); - res.x = size->x; - res.y = size->y; - res.w = size->width; - res.h = size->height; - } - if (std::string (event->type) == "object:text-caret-moved" && (res.w > 50 || res.h > 70)) { // this is obviously not a caret size - AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); - res.x = size->x; - res.y = size->y; - res.w = size->width; - res.h = size->height; - if (type == "caret" && std::string (event->type) == "object:text-caret-moved" && (res.w > 50 || res.h > 70)) { - res.x = 0; - res.y = 0; - } - } - if (res.x == 0 && res.y == 0 && // still no offset, it's probably a newline - (std::string (event->type) == "object:text-changed:insert" || - std::string (event->type) == "object:text-changed:removed" || - std::string (event->type) == "object:text-caret-moved")) { - res.x = res.x_alt; - res.y = res.y_alt; - res.w = res.w_alt; - res.h = res.h_alt; - } + auto text = atspi_accessible_get_text (event->source); + if (!text) { + return; + } + auto offset = atspi_text_get_caret_offset (text, NULL); + if (event->detail1) { // if we're at the beginning of text, let the widget pos decide TODO check that + AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); + res.x = size->x; + res.y = size->y; + res.w = size->width; + res.h = size->height; + } + if (res.x == 0 && res.y == 0 && offset > 0) { // correcting a missing offset to a caret move event in ff TODO file bug + AtspiRect *size = atspi_text_get_character_extents (text, offset-1, ATSPI_COORD_TYPE_SCREEN, NULL); + res.x = size->x; + res.y = size->y; + res.w = size->width; + res.h = size->height; + } + if (std::string (event->type) == "object:text-caret-moved" && (res.w > 50 || res.h > 70)) { // this is obviously not a caret size + AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); + res.x = size->x; + res.y = size->y; + res.w = size->width; + res.h = size->height; + if (type == "caret" && std::string (event->type) == "object:text-caret-moved" && (res.w > 50 || res.h > 70)) { + res.x = 0; + res.y = 0; + } + } + if (res.x == 0 && res.y == 0 && // still no offset, it's probably a newline + (std::string (event->type) == "object:text-changed:insert" || + std::string (event->type) == "object:text-changed:removed" || + std::string (event->type) == "object:text-caret-moved")) { + res.x = res.x_alt; + res.y = res.y_alt; + res.w = res.w_alt; + res.h = res.h_alt; + } } // getting the states on event auto state_set = atspi_accessible_get_state_set (event->source); if (atspi_state_set_contains (state_set, ATSPI_STATE_FOCUSED)) { - res.focused = true; - AccessibilityWatcher::get_instance ()->_previously_active_menus.clear (); // reset potential menu stack + res.focused = true; + AccessibilityWatcher::get_instance ()->_previously_active_menus.clear (); // reset potential menu stack } if (atspi_state_set_contains (state_set, ATSPI_STATE_SELECTED)) { // never works, GTK Bad implem? - res.selected = true; + res.selected = true; } if (res.type == "state-changed:selected" && event->detail1 == 1) { - res.selected = true; - AccessibilityWatcher::get_instance ()->_previously_active_menus.push_back (res); // add to stack of menus + res.selected = true; + AccessibilityWatcher::get_instance ()->_previously_active_menus.push_back (res); // add to stack of menus } if (app_specific_filter (res, event)) { - return; + return; } if (filter_bad_events (res)) { - return; + return; } while (AccessibilityWatcher::get_instance ()->_focus_list.size () >= 5) { // don't keep the whole history - AccessibilityWatcher::get_instance ()->_focus_list.erase (AccessibilityWatcher::get_instance ()->_focus_list.begin ()); + AccessibilityWatcher::get_instance ()->_focus_list.erase (AccessibilityWatcher::get_instance ()->_focus_list.begin ()); } AccessibilityWatcher::get_instance ()->_focus_list.push_back (res); } bool AccessibilityWatcher::app_specific_filter (FocusInfo& focus, const AtspiEvent* event) { if (focus.type == "state-changed:selected" && // emulates on-change:selected false behaviour. eg: for menus - (focus.role == "menu item" || - focus.role == "menu" || - focus.role == "check menu item" || - focus.role == "radio menu item") && - focus.application != "mate-panel") + (focus.role == "menu item" || + focus.role == "menu" || + focus.role == "check menu item" || + focus.role == "radio menu item") && + focus.application != "mate-panel") { - if (!focus.selected && AccessibilityWatcher::get_instance ()->return_to_prev_menu ()) { - return true; - } - focus.active = true; + if (!focus.selected && AccessibilityWatcher::get_instance ()->return_to_prev_menu ()) { + return true; + } + focus.active = true; } if (focus.application == "soffice" && focus.role == "paragraph") { // LO-calc: avoid spam event from main edit line - auto parent = atspi_accessible_get_parent (event->source, NULL); - std::string parent_label = atspi_accessible_get_name (parent, NULL); - if (parent_label == "Input line" || - parent_label == "Ligne de saisie") { - return true; - } + auto parent = atspi_accessible_get_parent (event->source, NULL); + std::string parent_label = atspi_accessible_get_name (parent, NULL); + if (parent_label == "Input line" || + parent_label == "Ligne de saisie") { + return true; + } } if (focus.application == "Icedove" || focus.application == "Thunderbird") { - if (focus.type == "caret") { - auto text = atspi_accessible_get_text (event->source); // next if deals with a special newline char, that remained buggy. hypra issue #430 - auto offset = atspi_text_get_caret_offset (text, NULL); - auto string = std::string (atspi_text_get_text_at_offset (text, offset, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); - auto string_m1 = std::string (atspi_text_get_text_at_offset (text, offset -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); - if (offset == atspi_text_get_character_count (text, NULL) && string == "\0" && (string_m1 == "\n" || int (string_m1.c_str ()[0]) == -17)) { - get_alternative_caret (focus, event); - focus.x = focus.x_alt; - focus.y = focus.y_alt + focus.h_alt; - focus.w = focus.w_alt; - focus.h = focus.h_alt; - } - if (! (focus.x == 0 && focus.y == 0)) { // prevents compose window loss of tracking in HTML mode (active flag ok, but no focused flag) - AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); - return true; - } - auto component = atspi_accessible_get_component (event->source); - if (component) { - AtspiRect* size = atspi_component_get_extents (component, ATSPI_COORD_TYPE_SCREEN, NULL); - focus.x = size->x; - focus.y = size->y; - focus.w = 7; - focus.h = size->height; - AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); - return true; - } - } + if (focus.type == "caret") { + auto text = atspi_accessible_get_text (event->source); // next if deals with a special newline char, that remained buggy. hypra issue #430 + auto offset = atspi_text_get_caret_offset (text, NULL); + auto string = std::string (atspi_text_get_text_at_offset (text, offset, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); + auto string_m1 = std::string (atspi_text_get_text_at_offset (text, offset -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); + if (offset == atspi_text_get_character_count (text, NULL) && string == "\0" && (string_m1 == "\n" || int (string_m1.c_str ()[0]) == -17)) { + get_alternative_caret (focus, event); + focus.x = focus.x_alt; + focus.y = focus.y_alt + focus.h_alt; + focus.w = focus.w_alt; + focus.h = focus.h_alt; + } + if (! (focus.x == 0 && focus.y == 0)) { // prevents compose window loss of tracking in HTML mode (active flag ok, but no focused flag) + AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); + return true; + } + auto component = atspi_accessible_get_component (event->source); + if (component) { + AtspiRect* size = atspi_component_get_extents (component, ATSPI_COORD_TYPE_SCREEN, NULL); + focus.x = size->x; + focus.y = size->y; + focus.w = 7; + focus.h = size->height; + AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); + return true; + } + } } if (focus.application == "Firefox") { - if (_ignore_links && focus.type != "caret" && focus.role == "link") { - return true; - } + if (_ignore_links && focus.type != "caret" && focus.role == "link") { + return true; + } // prevents status bar focus in firefox - if (focus.type == "caret" && - (static_cast (event->type) == "object:text-changed:insert:system" || - static_cast (event->type) == "object:text-changed:delete:system")) { - return true; - } + if (focus.type == "caret" && + (static_cast (event->type) == "object:text-changed:insert:system" || + static_cast (event->type) == "object:text-changed:delete:system")) { + return true; + } // general page parasite event - if (focus.type == "focus" && focus.role == "document frame") { - return true; - } - if (focus.type == "caret" && + if (focus.type == "focus" && focus.role == "document frame") { + return true; + } + if (focus.type == "caret" && !(focus.x == 0 && focus.y == 0) && !(focus.x < -2000 || focus.y < -2000)) { - AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); - return true; - } + AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); + return true; + } // assert whether we are inside a google document, then get kix caret if (getBrowserURL (event->source).find ("docs.google") != std::string::npos && AccessibilityWatcher::getKixCaret (focus, event)) { - AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); + AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); return true; } - get_alternative_caret (focus, event); + get_alternative_caret (focus, event); if (focus.type == "caret" && !(focus.x_alt == 0 && focus.y_alt == 0) && !(focus.x_alt < AccessibilityWatcher::get_instance ()->screenWidth * -1 || focus.y_alt < AccessibilityWatcher::get_instance ()->screenHeight * -1) @@ -291,27 +291,27 @@ bool AccessibilityWatcher::app_specific_filter (FocusInfo& focus, const AtspiEve } } if (focus.application == "evince" && focus.type == "state-changed:selected" && focus.role == "icon") { // LO-calc: avoid spam event from main edit line - return true; // ignores the parasite event from evince icon + return true; // ignores the parasite event from evince icon } return false; } bool AccessibilityWatcher::filter_bad_events (const FocusInfo& event) { if (event.type == "caret" && event.x ==0 && event.y == 0) { - return true; + return true; } if (!event.active) { - return true; + return true; } if (!event.focused && !event.selected) { - return true; + return true; } if (AccessibilityWatcher::get_instance ()->screenWidth != 0 && AccessibilityWatcher::get_instance ()->screenHeight !=0 && - (event.x > AccessibilityWatcher::get_instance ()->screenWidth || - event.y > AccessibilityWatcher::get_instance ()->screenHeight || // TODO remove when non-singleton - event.x < 0 || - event.y < 0 )) { - return true; + (event.x > AccessibilityWatcher::get_instance ()->screenWidth || + event.y > AccessibilityWatcher::get_instance ()->screenHeight || // TODO remove when non-singleton + event.x < 0 || + event.y < 0 )) { + return true; } return false; } @@ -352,12 +352,12 @@ AccessibilityWatcher::getBrowserURL (AtspiAccessible* accessible) * no idea whether this is a fail in GTK, or in ATSPI */ bool AccessibilityWatcher::return_to_prev_menu () { - if (_previously_active_menus.size () > 1) { - _previously_active_menus.pop_back (); - _focus_list.push_back (_previously_active_menus.back ()); - return true; - } - return false; + if (_previously_active_menus.size () > 1) { + _previously_active_menus.pop_back (); + _focus_list.push_back (_previously_active_menus.back ()); + return true; + } + return false; } /* @@ -445,38 +445,38 @@ void AccessibilityWatcher::get_alternative_caret (FocusInfo& focus, const AtspiE auto caret_char = std::string (atspi_text_get_text_at_offset (text, offset, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); bool has_seen_17 = false; if (caret_char == "\n" || caret_char == "\0") { // if we're at a newline, sometimes ATSPI doesn't feel like giving us a caret position. - int lines = 0; - if (atspi_text_get_character_count (text, NULL) == offset) { - lines++; // gives the last empty line the right focus. - } - int it = 1; - bool char_extents_found = false; - AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); - while (!char_extents_found && it <= offset && it < 300) { // try and find the character on upper line to extrapolate from - size = atspi_text_get_character_extents (text, offset - it, ATSPI_COORD_TYPE_SCREEN, NULL); - caret_char = atspi_text_get_text_at_offset (text, offset -it, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content; - if ((size->x != 0 || size->y != 0) && int (caret_char[0]) != -17) { // if we found a caret, check we're at beginning of line (or of text) - if (offset -it -1 >= 0 && std::string (atspi_text_get_text_at_offset (text, offset -it -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content) == "\n") { - char_extents_found = true; // first character of upper line has been found - } else if (offset -it -1 == 0) { - size = atspi_text_get_character_extents (text, 0, ATSPI_COORD_TYPE_SCREEN, NULL); - char_extents_found = true; // first character of upper line has been found - } - } else if (caret_char == "\n" || int (caret_char[0]) == -17) { - lines ++; - } - if (!has_seen_17 && int (caret_char[0]) == -17 ) { - has_seen_17 = true; - } - it ++; - } - if (!has_seen_17) { - lines--; - } - focus.x_alt = size->x; - focus.y_alt = size->y + (lines-1) * size->height; - focus.w_alt = size->width; - focus.h_alt = size->height; + int lines = 0; + if (atspi_text_get_character_count (text, NULL) == offset) { + lines++; // gives the last empty line the right focus. + } + int it = 1; + bool char_extents_found = false; + AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); + while (!char_extents_found && it <= offset && it < 300) { // try and find the character on upper line to extrapolate from + size = atspi_text_get_character_extents (text, offset - it, ATSPI_COORD_TYPE_SCREEN, NULL); + caret_char = atspi_text_get_text_at_offset (text, offset -it, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content; + if ((size->x != 0 || size->y != 0) && int (caret_char[0]) != -17) { // if we found a caret, check we're at beginning of line (or of text) + if (offset -it -1 >= 0 && std::string (atspi_text_get_text_at_offset (text, offset -it -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content) == "\n") { + char_extents_found = true; // first character of upper line has been found + } else if (offset -it -1 == 0) { + size = atspi_text_get_character_extents (text, 0, ATSPI_COORD_TYPE_SCREEN, NULL); + char_extents_found = true; // first character of upper line has been found + } + } else if (caret_char == "\n" || int (caret_char[0]) == -17) { + lines ++; + } + if (!has_seen_17 && int (caret_char[0]) == -17 ) { + has_seen_17 = true; + } + it ++; + } + if (!has_seen_17) { + lines--; + } + focus.x_alt = size->x; + focus.y_alt = size->y + (lines-1) * size->height; + focus.w_alt = size->width; + focus.h_alt = size->height; } } -- GitLab From 821e357dab3a18d70555cbabed525fe4d7ca340a Mon Sep 17 00:00:00 2001 From: ksamak Date: Tue, 23 May 2017 13:07:07 +0200 Subject: [PATCH 07/20] bump changelog --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 14047418f..1ca93820a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -compiz (2:0.9.12.2+hypra7.4) UNRELEASED; urgency=medium +compiz (2:0.9.12.2+hypra7.4.1) UNRELEASED; urgency=medium * Switch to native versioning to overcome big changes from the last known upstream tarball (which contains extra files). -- GitLab From e3f7219f85949779145f8fb9b22f769585be3dee Mon Sep 17 00:00:00 2001 From: ksamak Date: Thu, 25 May 2017 17:35:55 +0200 Subject: [PATCH 08/20] resolved a segfault bug, some cleanup, optimisation, and saved computing time when focuspoll is idle --- plugins/ezoom/src/ezoom.cpp | 39 +++++++-------- .../accessibilitywatcher.h | 2 + .../focuspoll/src/accessibilitywatcher.cpp | 22 +++++++-- plugins/focuspoll/src/focuspoll.cpp | 35 +++++++------ plugins/focuspoll/src/private.h | 2 +- plugins/mousepoll/CMakeLists.txt | 4 ++ .../mousepoll/include/mousepoll/mousepoll.h | 6 +-- plugins/mousepoll/src/mousepoll.cpp | 49 ++++++++----------- plugins/mousepoll/src/private.h | 4 +- 9 files changed, 86 insertions(+), 77 deletions(-) diff --git a/plugins/ezoom/src/ezoom.cpp b/plugins/ezoom/src/ezoom.cpp index 19d7279a3..8f9fad397 100644 --- a/plugins/ezoom/src/ezoom.cpp +++ b/plugins/ezoom/src/ezoom.cpp @@ -1123,26 +1123,24 @@ EZoomScreen::cursorMoved () void EZoomScreen::updateMousePosition(const CompPoint &p) { - if (pollMouseHandle.mouseHasMoved()) { - mousePos = pollMouseHandle.getMousePosition(); - int out = screen->outputDeviceForPoint(mousePos.x(), mousePos.y()); - if (optionGetZoomMode() == EzoomOptions::ZoomModeSyncMouse && !isInMovement(out)) { - if (optionGetWarpMouseToFocus()) { - if (lastMouseChange <= lastFocusChange) { // mouse taking back control of focus - lastMouseChange = time(NULL); - _non_mouse_focus_tracking = false; - screen->warpPointer(mousePos.x(), mousePos.y()); - restrainCursor(out); - } else { - setCenter(mousePos.x(), mousePos.y(), true, optionGetAlwaysCenterMouse()); - lastMouseChange = time(NULL); - } - } else if (time(NULL) - lastFocusChange > optionGetFollowFocusDelay()) { - setCenter(mousePos.x(), mousePos.y(), true, optionGetAlwaysCenterMouse()); - lastMouseChange = time(NULL); - } - } - } + mousePos = pollMouseHandle.getPosition(); + int out = screen->outputDeviceForPoint(mousePos.x(), mousePos.y()); + if (optionGetZoomMode() == EzoomOptions::ZoomModeSyncMouse && !isInMovement(out)) { + if (optionGetWarpMouseToFocus()) { + if (lastMouseChange <= lastFocusChange) { // mouse taking back control of focus + lastMouseChange = time(NULL); + _non_mouse_focus_tracking = false; + screen->warpPointer(mousePos.x(), mousePos.y()); + restrainCursor(out); + } else { + setCenter(mousePos.x(), mousePos.y(), true, optionGetAlwaysCenterMouse()); + lastMouseChange = time(NULL); + } + } else if (time(NULL) - lastFocusChange > optionGetFollowFocusDelay()) { + setCenter(mousePos.x(), mousePos.y(), true, optionGetAlwaysCenterMouse()); + lastMouseChange = time(NULL); + } + } } void @@ -1164,7 +1162,6 @@ EZoomScreen::updateFocusPosition(const CompRect &rect) _non_mouse_focus_tracking = true; lastFocusChange = time(NULL); } - cursorMoved(); cScreen->damageScreen(); } diff --git a/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h b/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h index 04f296923..97ff184b0 100644 --- a/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h +++ b/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h @@ -34,6 +34,7 @@ class AccessibilityWatcher { ~AccessibilityWatcher() {quit();}; void init(); + void setActive (bool); void quit(); void setIgnoreLinks(bool); @@ -54,6 +55,7 @@ class AccessibilityWatcher { static Display* dpy; bool _initialized; + bool mActive; static bool _ignore_links; static const int _timeout_ms = 20; std::deque _focus_list; diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index 27717bd1e..0a12f81de 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -32,7 +32,8 @@ bool AccessibilityWatcher::_ignore_links = false; AccessibilityWatcher::AccessibilityWatcher () : screenWidth (0), screenHeight (0), - _initialized (false) + _initialized (false), + mActive(true) { } @@ -112,7 +113,7 @@ void AccessibilityWatcher::register_event(const AtspiEvent *event, std::string t if (atspi_state_set_contains (state_set, ATSPI_STATE_ACTIVE)) { res.active = true; } - child = atspi_accessible_get_parent (child, NULL); + child = atspi_accessible_get_parent (child, NULL); // TODO C cleanup } AtspiComponent* component; @@ -320,7 +321,7 @@ std::string AccessibilityWatcher::getBrowserURL (AtspiAccessible* accessible) { if (!accessible) - return NULL; + return ""; AtspiAccessible* parent = accessible; while (parent != NULL) @@ -343,7 +344,7 @@ AccessibilityWatcher::getBrowserURL (AtspiAccessible* accessible) g_hash_table_destroy (attributes); g_object_unref (document); } - return NULL; + return ""; } @@ -535,6 +536,19 @@ void AccessibilityWatcher::init () { _initialized = true; } +void +AccessibilityWatcher::setActive (bool activate) +{ + if (mActive && !activate) + { + removeWatches(); + } + else if (!mActive && activate) + { + addWatches(); + } +} + void AccessibilityWatcher::quit () { removeWatches (); _initialized = false; diff --git a/plugins/focuspoll/src/focuspoll.cpp b/plugins/focuspoll/src/focuspoll.cpp index c27a1974e..1598a61a1 100644 --- a/plugins/focuspoll/src/focuspoll.cpp +++ b/plugins/focuspoll/src/focuspoll.cpp @@ -26,12 +26,15 @@ COMPIZ_PLUGIN_20090315 (focuspoll, FocuspollPluginVTable); bool FocuspollScreen::updatePosition () { if (!a11ywatcher->get_focus_queue().empty()) { - int focusX, focusY, focusW, focusH; - std::tie(focusX, focusY, focusW, focusH) = a11ywatcher->get_focus_queue().back().getBBox(); - focusRect = CompRect(focusX, focusY, focusW, focusH); - for (auto poller : pollers) { - poller->mCallback(focusRect); - } + int focusX, focusY, focusW, focusH; + std::tie(focusX, focusY, focusW, focusH) = a11ywatcher->get_focus_queue().back().getBBox(); + focusRect = CompRect(focusX, focusY, focusW, focusH); + for (std::list::iterator it = pollers.begin (); it != pollers.end ();) + { + FocusPoller *poller = *it; + ++it; + poller->mCallback(focusRect); + } } a11ywatcher->reset_focus_queue(); return true; @@ -53,6 +56,7 @@ FocuspollScreen::addTimer (FocusPoller *poller) if (start) { //focusHasMoved(); + a11ywatcher->setActive(true); timer.start(); } @@ -71,6 +75,8 @@ FocuspollScreen::removeTimer (FocusPoller *poller) pollers.erase (it); if (pollers.empty ()) + { + a11ywatcher->setActive(false); timer.stop (); } @@ -93,7 +99,7 @@ FocusPoller::start () { FOCUSPOLL_SCREEN (screen); - if (!ms) + if (!fs) { compLogMessage ("focuspoll", CompLogLevelWarn, "Plugin version mismatch, can't start focus poller."); @@ -108,7 +114,7 @@ FocusPoller::start () return; } - ms->addTimer (this); + fs->addTimer (this); mActive = true; } @@ -123,7 +129,7 @@ FocusPoller::stop () if (!mActive) return; - if (!ms) + if (!fs) { compLogMessage ("focuspoll", CompLogLevelWarn, @@ -133,7 +139,7 @@ FocusPoller::stop () mActive = false; - ms->removeTimer (this); + fs->removeTimer (this); } bool @@ -174,16 +180,13 @@ template class PluginClassHandler (screen) { - std::cout << "starting focuspoll" << std::endl; a11ywatcher = AccessibilityWatcher::get_instance(); a11ywatcher->init(); - int screenLimitX, screenLimitY; - std::tie(screenLimitX, screenLimitY) = getScreenLimits(); - a11ywatcher->setScreenLimits(screenLimitX, screenLimitY); - std::cout << "started a11y watcher" << std::endl; + int screenLimitX, screenLimitY; + std::tie(screenLimitX, screenLimitY) = getScreenLimits(); + a11ywatcher->setScreenLimits(screenLimitX, screenLimitY); updateTimer (); timer.setCallback (boost::bind (&FocuspollScreen::updatePosition, this)); - std::cout << "set focus timer callback" << std::endl; optionSetFocusPollIntervalNotify (boost::bind (&FocuspollScreen::updateTimer, this)); } diff --git a/plugins/focuspoll/src/private.h b/plugins/focuspoll/src/private.h index 60f5a8a90..601fb417e 100644 --- a/plugins/focuspoll/src/private.h +++ b/plugins/focuspoll/src/private.h @@ -63,7 +63,7 @@ class FocuspollScreen : }; #define FOCUSPOLL_SCREEN(s) \ - FocuspollScreen *ms = FocuspollScreen::get (s) + FocuspollScreen *fs = FocuspollScreen::get (s) #define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption)) diff --git a/plugins/mousepoll/CMakeLists.txt b/plugins/mousepoll/CMakeLists.txt index d4b00e5d6..abc6a5786 100644 --- a/plugins/mousepoll/CMakeLists.txt +++ b/plugins/mousepoll/CMakeLists.txt @@ -1 +1,5 @@ +find_package (Compiz REQUIRED) + +include (CompizPlugin) + compiz_plugin (mousepoll) diff --git a/plugins/mousepoll/include/mousepoll/mousepoll.h b/plugins/mousepoll/include/mousepoll/mousepoll.h index d87ed8735..e0469fd24 100644 --- a/plugins/mousepoll/include/mousepoll/mousepoll.h +++ b/plugins/mousepoll/include/mousepoll/mousepoll.h @@ -44,8 +44,8 @@ class MousePoller bool active (); - bool mouseHasMoved(); - CompPoint getMousePosition(); + CompPoint + getPosition (); static CompPoint getCurrentPosition (); @@ -54,8 +54,6 @@ class MousePoller bool mActive; CompPoint mPoint; - bool _has_mouse_moved; - CallBack mCallback; friend class MousepollScreen; diff --git a/plugins/mousepoll/src/mousepoll.cpp b/plugins/mousepoll/src/mousepoll.cpp index 0a677192b..7b7e71781 100644 --- a/plugins/mousepoll/src/mousepoll.cpp +++ b/plugins/mousepoll/src/mousepoll.cpp @@ -40,9 +40,9 @@ MousepollScreen::getMousePosition () if (!status || rootX > w || rootY > h || screen->root () != root) return false; - if (rootX != mousePos.x () || rootY != mousePos.y ()) + if (rootX != pos.x () || rootY != pos.y ()) { - mousePos.set (rootX, rootY); + pos.set (rootX, rootY); return true; } @@ -52,19 +52,19 @@ MousepollScreen::getMousePosition () bool MousepollScreen::updatePosition () { - _has_mouse_moved = getMousePosition(); - - if (_has_mouse_moved) { - for (std::list::iterator it = pollers.begin (); it != pollers.end ();) { - MousePoller *poller = *it; - - ++it; - poller->mPoint = mousePos; - poller->_has_mouse_moved = _has_mouse_moved; - poller->mCallback (mousePos); - } + if (getMousePosition ()) + { + for (std::list::iterator it = pollers.begin (); + it != pollers.end ();) + { + MousePoller *poller = *it; + + ++it; + poller->mPoint = pos; + poller->mCallback (pos); + } } - _has_mouse_moved = false; + return true; } @@ -186,25 +186,22 @@ MousePoller::getCurrentPosition () else { ms->getMousePosition (); - p = ms->mousePos; + p = ms->pos; } return p; } -CompPoint MousePoller::getMousePosition() { +CompPoint +MousePoller::getPosition () +{ return mPoint; } -bool MousePoller::mouseHasMoved() { - return _has_mouse_moved; -} - MousePoller::MousePoller () : - mActive(false), - mPoint(0, 0), - _has_mouse_moved(true), - mCallback(NULL) + mActive (false), + mPoint (0, 0), + mCallback (NULL) { } @@ -231,10 +228,6 @@ MousepollScreen::MousepollScreen (CompScreen *screen) : timer.setCallback (boost::bind (&MousepollScreen::updatePosition, this)); optionSetMousePollIntervalNotify (boost::bind (&MousepollScreen::updateTimer, this)); - -} - -MousepollScreen::~MousepollScreen() { } bool diff --git a/plugins/mousepoll/src/private.h b/plugins/mousepoll/src/private.h index 6d850d130..c21fb298d 100644 --- a/plugins/mousepoll/src/private.h +++ b/plugins/mousepoll/src/private.h @@ -44,13 +44,11 @@ class MousepollScreen : public: MousepollScreen (CompScreen *screen); - ~MousepollScreen (); std::list pollers; CompTimer timer; - CompPoint mousePos; - bool _has_mouse_moved; + CompPoint pos; bool updatePosition (); -- GitLab From d737e9a80f28d28b798d22926bce72762e404e05 Mon Sep 17 00:00:00 2001 From: ksamak Date: Mon, 29 May 2017 16:52:05 +0200 Subject: [PATCH 09/20] focuspoll: merged lp:~ksamak/compiz/ezoom_focus_tracking proposal --- plugins/focuspoll/focuspoll.xml.in | 14 +- .../accessibilitywatcher.h | 96 ++-- .../include/accessibilitywatcher/focusinfo.h | 170 ++---- .../focuspoll/include/focuspoll/focuspoll.h | 49 +- .../focuspoll/src/accessibilitywatcher.cpp | 498 ++++++++++-------- plugins/focuspoll/src/focusinfo.cpp | 130 +++++ plugins/focuspoll/src/focuspoll.cpp | 76 +-- plugins/focuspoll/src/private.h | 31 +- 8 files changed, 601 insertions(+), 463 deletions(-) create mode 100644 plugins/focuspoll/src/focusinfo.cpp diff --git a/plugins/focuspoll/focuspoll.xml.in b/plugins/focuspoll/focuspoll.xml.in index 462661a5d..7fe45862f 100644 --- a/plugins/focuspoll/focuspoll.xml.in +++ b/plugins/focuspoll/focuspoll.xml.in @@ -21,13 +21,13 @@ <_long>if enabled, focuspoll will not track the focus events of link items true - + diff --git a/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h b/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h index 97ff184b0..e19e31d14 100644 --- a/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h +++ b/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h @@ -1,28 +1,27 @@ /* - * Coyright (C) 2016 Auboyneau Vincent + * Copyright (C) 2016 Auboyneau Vincent + * + * This file is part of compiz. * * this program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * - * mate-accessibility is distributed in the hope that it will be useful, but + * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along - * with mate-accessibility. If not, see . + * with this program. If not, see . */ #ifndef ACCESSIBILITY_WATCHER_H #define ACCESSIBILITY_WATCHER_H -#include -#include #include #include -#include #include "focusinfo.h" @@ -30,61 +29,60 @@ class AccessibilityWatcher { public: - static AccessibilityWatcher* get_instance(); - ~AccessibilityWatcher() {quit();}; + ~AccessibilityWatcher(); + static AccessibilityWatcher* getInstance(); - void init(); + void init(); + void quit(); void setActive (bool); - void quit(); - - void setIgnoreLinks(bool); - void setScreenLimits(int, int); - std::deque get_focus_queue(); - void reset_focus_queue(); - bool return_to_prev_menu(); + void setIgnoreLinks(bool); + void setScreenLimits(int, int); + int getScreenWidth(); + int getScreenHeight(); - int screenWidth; - int screenHeight; + std::deque getFocusQueue(); + void resetFocusQueue(); + bool returnToPrevMenu(); private: - AccessibilityWatcher(); - static AccessibilityWatcher* _instance; + AccessibilityWatcher(); + static AccessibilityWatcher* instance; - // screen vars - static Display* dpy; - - bool _initialized; + bool initialized; bool mActive; - static bool _ignore_links; - static const int _timeout_ms = 20; - std::deque _focus_list; - std::vector _previously_active_menus; - - void addWatches(); - void removeWatches(); - - static std::string get_label(AtspiAccessible *accessible); - static AtspiAccessible* find_child_slider(AtspiAccessible *accessible); - const static gchar* atspi_state_get_name (gint state); - static std::string get_state_set (AtspiAccessible *accessible); - - static void print_event(const AtspiEvent *event); - static void print_event(AtspiAccessible *access); - static void register_event(const AtspiEvent *event, std::string type); - static bool app_specific_filter(FocusInfo& focus_info, const AtspiEvent* event); - static bool filter_bad_events(const FocusInfo& event); + int screenWidth; + int screenHeight; + static bool ignoreLinks; + std::deque focusList; + std::vector previouslyActiveMenus; + + AtspiEventListener *focusListener; + AtspiEventListener *caretMoveListener; + AtspiEventListener *selectedListener; + AtspiEventListener *descendantChangedListener; + + void addWatches(); + void removeWatches(); + + static std::string getLabel(AtspiAccessible *accessible); + const static gchar* atspiStateGetName (gint state); + static std::string getStateSet (AtspiAccessible *accessible); + + static void printEvent(const AtspiEvent *event); + static void printEvent(AtspiAccessible *access); + static void registerEvent(const AtspiEvent *event, const std::string& type); + static bool appSpecificFilter(FocusInfo& focusInfo, const AtspiEvent* event); + static bool filterBadEvents(const FocusInfo& event); static std::string getBrowserURL(AtspiAccessible*); static bool getKixCaret (FocusInfo&, const AtspiEvent*); static AtspiAccessible* recurseFindCursor(AtspiAccessible*); - static void get_alternative_caret(FocusInfo& focus, const AtspiEvent* event); - - static void on_focus(const AtspiEvent *event, void *data); - static void on_selected_change(const AtspiEvent *event, void *data); - static void on_caret_move(const AtspiEvent *event, void *data); - static void on_descendant_changed(const AtspiEvent *event, void *data); + static void getAlternativeCaret(FocusInfo& focus, const AtspiEvent* event); - AtspiEventListener *listener, *listener2, *listener3, *listener4; + static void onFocus(const AtspiEvent *event, void *data); + static void onSelectedChange(const AtspiEvent *event, void *data); + static void onCaretMove(const AtspiEvent *event, void *data); + static void onDescendantChanged(const AtspiEvent *event, void *data); }; diff --git a/plugins/focuspoll/include/accessibilitywatcher/focusinfo.h b/plugins/focuspoll/include/accessibilitywatcher/focusinfo.h index fdeeb189a..b9d3e7555 100644 --- a/plugins/focuspoll/include/accessibilitywatcher/focusinfo.h +++ b/plugins/focuspoll/include/accessibilitywatcher/focusinfo.h @@ -1,7 +1,25 @@ +/* + * Copyright (C) 2016 Auboyneau Vincent + * + * This file is part of compiz. + * + * this program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + #ifndef FOCUS_INFO_H #define FOCUS_INFO_H -#include #include #include #include @@ -9,126 +27,50 @@ class FocusInfo { public: - FocusInfo() { - x=0; y=0; - w=0; h=0; - x_alt=0; y_alt=0; - w_alt=0; h_alt=0; - type=""; - name = ""; - label=""; - role = ""; - application = ""; - enabled = false; - active = false; - focusable = false; - focused = false; - selected = false; - showing = false; - visible = false; - }; - - FocusInfo(const std::string& type, const std::string& name, const std::string& label, const std::string& role, const std::string& application, int x, int y, int width, int height) : - x(x), y(y), - w(width), h(height), - type(type), - name(name), - label(label), - role(role), - application(application), - enabled(false), - active(false), - focusable(false), - focused(false), - selected(false), - showing(false), - visible(false) - {}; - FocusInfo(std::string& type, std::string& name, std::string& label, std::string& role, std::string& application, int x, int y, int width, int height) : - x(x), y(y), - w(width), h(height), - type(type), - name(name), - label(label), - role(role), - application(application), - enabled(false), - active(false), - focusable(false), - focused(false), - selected(false), - showing(false), - visible(false) - {}; + FocusInfo(const std::string& type, + const std::string& name, + const std::string& label, + const std::string& role, + const std::string& application, + int x, + int y, + int width, + int height); - std::string getType() const {return type;}; // return caret or widget for now // TODO make const - std::tuple getPosition() const {return std::make_tuple(x, y);}; - std::tuple getSize() const {return std::make_tuple(w, h);}; - std::tuple getBBox() const {return std::make_tuple(x, y, w, h);}; + FocusInfo(const std::string& type, + const std::string& name, + const std::string& label, + const std::string& role, + const std::string& application); - bool operator==(const FocusInfo& other) const { - return (other.x == x && - other.y == y && - other.w == w && - other.h == h && - other.type == type && - other.name == name && - other.label == label && - other.application == application && - other.role == role); - }; + FocusInfo(); - bool operator!=(const FocusInfo& other) const { - return (other.x == x || - other.y == y || - other.w == w || - other.h == h || - other.type == type || - other.name == name || - other.label == label || - other.application == application || - other.role == role); - }; + int x, y, w, h; + int xAlt, yAlt, wAlt, hAlt; + std::string type; + std::string name; + std::string label; + std::string role; + std::string application; - std::string summary() const { - std::ostringstream res; - res << "name:" << name; - res << " application:" << application; - res << " type:" << type; - if (label != "") {res << " label:" << label;} - res << " role:" << role; - res << " pos " << x << "," << y; - res << "(" << w << ":" << h << ")"; - //res << std::endl; - res << "["; - //if (enabled) {res << "enabled ";} - if (active) {res << "active ";} - //if (focusable) {res << "focusable ";} - if (focused) {res << "focused ";} - if (selected) {res << "selected ";} - //if (showing) {res << "showing ";} - //if (visible) {res << "visible ";} - res << "]"; - return res.str(); - } + // AT-SPI events that are interesting to know about the event + bool enabled; + bool active; + bool focusable; + bool focused; + bool selected; + bool showing; + bool visible; - int x, y, w, h; - int x_alt, y_alt, w_alt, h_alt; - std::string type; - std::string name; - std::string label; - std::string role; - std::string application; + std::string getType(); + std::string summary(); + std::tuple getPosition(); + std::tuple getSize(); + std::tuple getBBox(); - // AT-SPI events that are interesting to know about the event - bool enabled; - bool active; - bool focusable; - bool focused; - bool selected; - bool showing; - bool visible; + bool operator== (const FocusInfo& other) const; + bool operator!= (const FocusInfo& other) const; }; #endif diff --git a/plugins/focuspoll/include/focuspoll/focuspoll.h b/plugins/focuspoll/include/focuspoll/focuspoll.h index 07bf45e4c..d194badad 100644 --- a/plugins/focuspoll/include/focuspoll/focuspoll.h +++ b/plugins/focuspoll/include/focuspoll/focuspoll.h @@ -1,21 +1,20 @@ /* + * Copyright (C) 2016 Auboyneau Vincent * - * Compiz focus position polling plugin + * This file is part of compiz. * - * Copyright : (C) 2016 Auboyneau Vincent - * E-mail : ksamak@riseup.net + * this program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . */ #ifndef _COMPIZ_FOCUSPOLL_H @@ -23,28 +22,28 @@ #define COMPIZ_FOCUSPOLL_ABI 1 +#include #include class FocusPoller { public: - typedef boost::function CallBack; + typedef boost::function CallBack; - FocusPoller (); - ~FocusPoller (); + FocusPoller (); + ~FocusPoller (); - void setCallback (CallBack callback); - void start (); - void stop (); - bool active (); - //static CompPoint getCurrentPosition (); + void setCallback (CallBack callback); + void start (); + void stop (); + bool active (); private: - bool mActive; - CallBack mCallback; - CompRect focusRect; + bool mActive; + CallBack mCallback; + CompRect focusRect; - friend class FocuspollScreen; + friend class FocuspollScreen; }; #endif diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index 0a12f81de..d7c7ca80b 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -1,21 +1,20 @@ /* + * Copyright (C) 2016 Auboyneau Vincent * - * Compiz focus tracking plugin + * This file is part of compiz. * - * Copyright : (C) 2016 Auboyneau Vincent - * E-mail : ksamak@riseup.net + * this program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . */ #include @@ -26,44 +25,61 @@ #include "accessibilitywatcher.h" -AccessibilityWatcher* AccessibilityWatcher::_instance = NULL; -bool AccessibilityWatcher::_ignore_links = false; +namespace { + const int A11YWATCHER_MAX_CARET_WIDTH = 50; + const int A11YWATCHER_MAX_CARET_HEIGHT = 70; +} + +AccessibilityWatcher* AccessibilityWatcher::instance = NULL; +bool AccessibilityWatcher::ignoreLinks = false; AccessibilityWatcher::AccessibilityWatcher () : + initialized (false), screenWidth (0), - screenHeight (0), - _initialized (false), - mActive(true) + screenHeight (0) { } -AccessibilityWatcher* AccessibilityWatcher::get_instance () { - if (_instance == NULL) { - _instance = new AccessibilityWatcher (); +AccessibilityWatcher::~AccessibilityWatcher () { + quit (); +}; + +AccessibilityWatcher *AccessibilityWatcher::getInstance () { + if (instance == NULL) + { + instance = new AccessibilityWatcher (); } - return _instance; + return instance; } -std::string AccessibilityWatcher::get_label (AtspiAccessible *accessible) { - GArray *relations; - AtspiRelation *relation; - - relations = atspi_accessible_get_relation_set (accessible, NULL); - if (relations == NULL) { +std::string AccessibilityWatcher::getLabel (AtspiAccessible *accessible) { + GArray *relations = atspi_accessible_get_relation_set (accessible, NULL); + if (relations == NULL) + { return ""; } - for (unsigned i = 0; i < relations->len; i++) { + AtspiRelation *relation; + for (unsigned i = 0; i < relations->len; ++i) { relation = g_array_index (relations, AtspiRelation*, i); - if (atspi_relation_get_relation_type (relation) == ATSPI_RELATION_LABELLED_BY) { - return atspi_accessible_get_name (atspi_relation_get_target (relation, 0), NULL); + if (atspi_relation_get_relation_type (relation) == ATSPI_RELATION_LABELLED_BY) + { + g_array_free (relations, true); + g_object_unref (relations); + auto res_label = atspi_accessible_get_name (atspi_relation_get_target (relation, 0), NULL); + g_object_unref (relation); + return (res_label == NULL) ? "" : res_label; } } + if (relations->len > 0) + { + g_object_unref (relations); + } return ""; } void AccessibilityWatcher::setIgnoreLinks (bool val) { - _ignore_links = val; + ignoreLinks = val; } void AccessibilityWatcher::setScreenLimits (int x, int y) { @@ -71,136 +87,149 @@ void AccessibilityWatcher::setScreenLimits (int x, int y) { screenHeight = y; } -/* - * In some cases (or at least in the case of gnome-shell), the slider - * is a child of the object that receives the focus/selection, so we - * need to search for it. - */ -AtspiAccessible* AccessibilityWatcher::find_child_slider (AtspiAccessible *accessible) { - AtspiAccessible *child = NULL; - int i = 0; - - for (i = 0; i < atspi_accessible_get_child_count (accessible, NULL); i++) { - child = atspi_accessible_get_child_at_index (accessible, i, NULL); - if (atspi_accessible_get_role (child, NULL) == ATSPI_ROLE_SLIDER) { - break; - } - } - - return child; +int AccessibilityWatcher::getScreenWidth () { + return screenWidth; } -const gchar* AccessibilityWatcher::atspi_state_get_name (gint state) { - auto type_class = g_type_class_ref (ATSPI_TYPE_STATE_TYPE); - g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), ""); - - auto value = g_enum_get_value (G_ENUM_CLASS (type_class), state); - - return value->value_nick; +int AccessibilityWatcher::getScreenHeight () { + return screenHeight; } -void AccessibilityWatcher::register_event(const AtspiEvent *event, std::string type) { - FocusInfo res; - res.type = type; // registered from filter on calling event - res.name = atspi_accessible_get_name (event->source, NULL); - res.label = get_label (event->source); - res.role = atspi_accessible_get_role_name (event->source, NULL); - res.application = atspi_accessible_get_name (atspi_accessible_get_application (event->source, NULL), NULL); - - auto child = atspi_accessible_get_parent (event->source, NULL); - while (!res.active && child) { // prevents events that are actually from an active child. weird behaviour. - auto state_set = atspi_accessible_get_state_set (child); - if (atspi_state_set_contains (state_set, ATSPI_STATE_ACTIVE)) { - res.active = true; +void AccessibilityWatcher::registerEvent (const AtspiEvent *event, const std::string &type) { + // type is registered from filter on calling event + FocusInfo res (type, + atspi_accessible_get_name (event->source, NULL), + getLabel (event->source), + atspi_accessible_get_role_name (event->source, NULL), + atspi_accessible_get_name (atspi_accessible_get_application (event->source, NULL), NULL)); + + if (!res.active) + { + // prevents skipping events that are not designated as active. we check the activeness of parents. + auto parent = atspi_accessible_get_parent (event->source, NULL); + while (!res.active && parent) { + auto stateSet = atspi_accessible_get_state_set (parent); + if (atspi_state_set_contains (stateSet, ATSPI_STATE_ACTIVE)) + { + res.active = true; + } + g_object_unref (stateSet); + auto child = atspi_accessible_get_parent (parent, NULL); + g_object_unref (parent); + parent = child; } - child = atspi_accessible_get_parent (child, NULL); // TODO C cleanup + g_object_unref (parent); } AtspiComponent* component; - if (res.type == "active-descendant-changed") { + if (res.type == "active-descendant-changed") + { auto accessible = atspi_accessible_get_child_at_index (event->source, event->detail1, NULL); component = atspi_accessible_get_component (accessible); + g_object_unref (accessible); } else { component = atspi_accessible_get_component (event->source); } - if (component) { + if (component) + { AtspiRect* size = atspi_component_get_extents (component, ATSPI_COORD_TYPE_SCREEN, NULL); res.x = size->x; res.y = size->y; res.w = size->width; res.h = size->height; + g_object_unref (component); } // let's get the caret offset, and then its position for a caret event - if (type == "caret") { + if (type == "caret") + { auto text = atspi_accessible_get_text (event->source); - if (!text) { + if (!text) + { return; } auto offset = atspi_text_get_caret_offset (text, NULL); - if (event->detail1) { // if we're at the beginning of text, let the widget pos decide TODO check that + // if we're at the beginning of text, let the widget pos decide + if (event->detail1) + { AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); res.x = size->x; res.y = size->y; res.w = size->width; res.h = size->height; } - if (res.x == 0 && res.y == 0 && offset > 0) { // correcting a missing offset to a caret move event in ff TODO file bug + // correcting a missing offset to a caret move event in firefox + if (res.x == 0 && res.y == 0 && offset > 0) + { AtspiRect *size = atspi_text_get_character_extents (text, offset-1, ATSPI_COORD_TYPE_SCREEN, NULL); res.x = size->x; res.y = size->y; res.w = size->width; res.h = size->height; } - if (std::string (event->type) == "object:text-caret-moved" && (res.w > 50 || res.h > 70)) { // this is obviously not a caret size + // when result is obviously not a caret size + if (strcmp (event->type, "object:text-caret-moved") == 0 && (res.w > A11YWATCHER_MAX_CARET_WIDTH || res.h > A11YWATCHER_MAX_CARET_HEIGHT)) + { AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); res.x = size->x; res.y = size->y; res.w = size->width; res.h = size->height; - if (type == "caret" && std::string (event->type) == "object:text-caret-moved" && (res.w > 50 || res.h > 70)) { + if (type == "caret" && strcmp (event->type, "object:text-caret-moved") == 0 && (res.w > A11YWATCHER_MAX_CARET_WIDTH || res.h > A11YWATCHER_MAX_CARET_HEIGHT)) + { res.x = 0; res.y = 0; } } - if (res.x == 0 && res.y == 0 && // still no offset, it's probably a newline - (std::string (event->type) == "object:text-changed:insert" || - std::string (event->type) == "object:text-changed:removed" || - std::string (event->type) == "object:text-caret-moved")) { - res.x = res.x_alt; - res.y = res.y_alt; - res.w = res.w_alt; - res.h = res.h_alt; + g_object_unref (text); + + // still no offset, it's probably a newline and we're at bugzilla #1319273 (with new paragraph obj) + if (res.x == 0 && res.y == 0 && + (strcmp (event->type, "object:text-changed:insert") == 0 || + strcmp (event->type, "object:text-changed:removed") == 0 || + strcmp (event->type, "object:text-caret-moved") == 0)) { + res.x = res.xAlt; + res.y = res.yAlt; + res.w = res.wAlt; + res.h = res.hAlt; } } // getting the states on event - auto state_set = atspi_accessible_get_state_set (event->source); - if (atspi_state_set_contains (state_set, ATSPI_STATE_FOCUSED)) { + auto stateSet = atspi_accessible_get_state_set (event->source); + if (atspi_state_set_contains (stateSet, ATSPI_STATE_FOCUSED)) + { res.focused = true; - AccessibilityWatcher::get_instance ()->_previously_active_menus.clear (); // reset potential menu stack + // reset potential menu stack + AccessibilityWatcher::getInstance ()->previouslyActiveMenus.clear (); } - if (atspi_state_set_contains (state_set, ATSPI_STATE_SELECTED)) { // never works, GTK Bad implem? + if (atspi_state_set_contains (stateSet, ATSPI_STATE_SELECTED)) + { // never works, GTK Bad implem? res.selected = true; } - if (res.type == "state-changed:selected" && event->detail1 == 1) { + if (res.type == "state-changed:selected" && event->detail1 == 1) + { res.selected = true; - AccessibilityWatcher::get_instance ()->_previously_active_menus.push_back (res); // add to stack of menus + // add to stack of menus + AccessibilityWatcher::getInstance ()->previouslyActiveMenus.push_back (res); } - if (app_specific_filter (res, event)) { + if (appSpecificFilter (res, event)) + { return; } - if (filter_bad_events (res)) { + if (filterBadEvents (res)) + { return; } - while (AccessibilityWatcher::get_instance ()->_focus_list.size () >= 5) { // don't keep the whole history - AccessibilityWatcher::get_instance ()->_focus_list.erase (AccessibilityWatcher::get_instance ()->_focus_list.begin ()); + while (AccessibilityWatcher::getInstance ()->focusList.size () >= 5) { // don't keep the whole history + AccessibilityWatcher::getInstance ()->focusList.erase (AccessibilityWatcher::getInstance ()->focusList.begin ()); } - AccessibilityWatcher::get_instance ()->_focus_list.push_back (res); + AccessibilityWatcher::getInstance ()->focusList.push_back (res); } -bool AccessibilityWatcher::app_specific_filter (FocusInfo& focus, const AtspiEvent* event) { +bool AccessibilityWatcher::appSpecificFilter (FocusInfo& focus, const AtspiEvent* event) +{ if (focus.type == "state-changed:selected" && // emulates on-change:selected false behaviour. eg: for menus (focus.role == "menu item" || focus.role == "menu" || @@ -208,50 +237,59 @@ bool AccessibilityWatcher::app_specific_filter (FocusInfo& focus, const AtspiEve focus.role == "radio menu item") && focus.application != "mate-panel") { - if (!focus.selected && AccessibilityWatcher::get_instance ()->return_to_prev_menu ()) { + if (!focus.selected && AccessibilityWatcher::getInstance ()->returnToPrevMenu ()) + { return true; } focus.active = true; } - if (focus.application == "soffice" && focus.role == "paragraph") { // LO-calc: avoid spam event from main edit line + if (focus.application == "soffice" && focus.role == "paragraph") + { // LO-calc: avoid spam event from main edit line auto parent = atspi_accessible_get_parent (event->source, NULL); - std::string parent_label = atspi_accessible_get_name (parent, NULL); - if (parent_label == "Input line" || - parent_label == "Ligne de saisie") { + std::string parentLabel = atspi_accessible_get_name (parent, NULL); + if (parentLabel == "Input line" || + parentLabel == "Ligne de saisie") { return true; } } - if (focus.application == "Icedove" || focus.application == "Thunderbird") { - if (focus.type == "caret") { + if (focus.application == "Icedove" || focus.application == "Thunderbird") + { + if (focus.type == "caret") + { auto text = atspi_accessible_get_text (event->source); // next if deals with a special newline char, that remained buggy. hypra issue #430 auto offset = atspi_text_get_caret_offset (text, NULL); auto string = std::string (atspi_text_get_text_at_offset (text, offset, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); - auto string_m1 = std::string (atspi_text_get_text_at_offset (text, offset -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); - if (offset == atspi_text_get_character_count (text, NULL) && string == "\0" && (string_m1 == "\n" || int (string_m1.c_str ()[0]) == -17)) { - get_alternative_caret (focus, event); - focus.x = focus.x_alt; - focus.y = focus.y_alt + focus.h_alt; - focus.w = focus.w_alt; - focus.h = focus.h_alt; + auto stringM1 = std::string (atspi_text_get_text_at_offset (text, offset -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); + if (offset == atspi_text_get_character_count (text, NULL) && string == "\0" && (stringM1 == "\n" || int (stringM1.c_str ()[0]) == -17)) + { + getAlternativeCaret (focus, event); + focus.x = focus.xAlt; + focus.y = focus.yAlt + focus.hAlt; + focus.w = focus.wAlt; + focus.h = focus.hAlt; } - if (! (focus.x == 0 && focus.y == 0)) { // prevents compose window loss of tracking in HTML mode (active flag ok, but no focused flag) - AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); + if (!(focus.x == 0 && focus.y == 0)) + { // prevents compose window loss of tracking in HTML mode (active flag ok, but no focused flag) + AccessibilityWatcher::getInstance ()->focusList.push_back (focus); return true; } auto component = atspi_accessible_get_component (event->source); - if (component) { + if (component) + { AtspiRect* size = atspi_component_get_extents (component, ATSPI_COORD_TYPE_SCREEN, NULL); focus.x = size->x; focus.y = size->y; focus.w = 7; focus.h = size->height; - AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); + AccessibilityWatcher::getInstance ()->focusList.push_back (focus); return true; } } } - if (focus.application == "Firefox") { - if (_ignore_links && focus.type != "caret" && focus.role == "link") { + if (focus.application == "Firefox") + { + if (ignoreLinks && focus.type != "caret" && focus.role == "link") + { return true; } // prevents status bar focus in firefox @@ -260,56 +298,59 @@ bool AccessibilityWatcher::app_specific_filter (FocusInfo& focus, const AtspiEve static_cast (event->type) == "object:text-changed:delete:system")) { return true; } - // general page parasite event - if (focus.type == "focus" && focus.role == "document frame") { - return true; - } - if (focus.type == "caret" && - !(focus.x == 0 && focus.y == 0) && - !(focus.x < -2000 || focus.y < -2000)) { - AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); + if (focus.type == "focus" && focus.role == "document frame") + { // general page parasite event return true; } // assert whether we are inside a google document, then get kix caret if (getBrowserURL (event->source).find ("docs.google") != std::string::npos && AccessibilityWatcher::getKixCaret (focus, event)) { - AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); + AccessibilityWatcher::getInstance ()->focusList.push_back (focus); return true; } - - get_alternative_caret (focus, event); + if (focus.type == "caret" && !(focus.x == 0 && focus.y == 0)) + { + AccessibilityWatcher::getInstance ()->focusList.push_back (focus); + return true; + } + getAlternativeCaret (focus, event); if (focus.type == "caret" && - !(focus.x_alt == 0 && focus.y_alt == 0) && - !(focus.x_alt < AccessibilityWatcher::get_instance ()->screenWidth * -1 || focus.y_alt < AccessibilityWatcher::get_instance ()->screenHeight * -1) - ) { - focus.x = focus.x_alt; - focus.y = focus.y_alt + focus.h_alt; - focus.w = focus.w_alt; - focus.h = focus.h_alt; - AccessibilityWatcher::get_instance ()->_focus_list.push_back (focus); + !(focus.xAlt == 0 && focus.yAlt == 0) && + !(focus.xAlt < AccessibilityWatcher::getInstance ()->screenWidth * -1 || focus.yAlt < AccessibilityWatcher::getInstance ()->screenHeight * -1) + ) + { + focus.x = focus.xAlt; + focus.y = focus.yAlt + focus.hAlt; + focus.w = focus.wAlt; + focus.h = focus.hAlt; + AccessibilityWatcher::getInstance ()->focusList.push_back (focus); return true; } } - if (focus.application == "evince" && focus.type == "state-changed:selected" && focus.role == "icon") { // LO-calc: avoid spam event from main edit line + if (focus.application == "evince" && focus.type == "state-changed:selected" && focus.role == "icon") + { // LO-calc: avoid spam event from main edit line return true; // ignores the parasite event from evince icon } return false; } -bool AccessibilityWatcher::filter_bad_events (const FocusInfo& event) { - if (event.type == "caret" && event.x ==0 && event.y == 0) { +bool AccessibilityWatcher::filterBadEvents (const FocusInfo& event) { + if (event.type == "caret" && event.x ==0 && event.y == 0) + { return true; } - if (!event.active) { + if (!event.active) + { return true; } - if (!event.focused && !event.selected) { + if (!event.focused && !event.selected) + { return true; } - if (AccessibilityWatcher::get_instance ()->screenWidth != 0 && AccessibilityWatcher::get_instance ()->screenHeight !=0 && - (event.x > AccessibilityWatcher::get_instance ()->screenWidth || - event.y > AccessibilityWatcher::get_instance ()->screenHeight || // TODO remove when non-singleton + if (AccessibilityWatcher::getInstance ()->getScreenWidth () != 0 && AccessibilityWatcher::getInstance ()->getScreenHeight () !=0 && + (event.x > AccessibilityWatcher::getInstance ()->getScreenWidth () || + event.y > AccessibilityWatcher::getInstance ()->getScreenHeight () || // TODO remove when non-singleton event.x < 0 || event.y < 0 )) { return true; @@ -352,10 +393,11 @@ AccessibilityWatcher::getBrowserURL (AtspiAccessible* accessible) * this is meant to emulate the missing "selected" argument in menu hierarchy. * no idea whether this is a fail in GTK, or in ATSPI */ -bool AccessibilityWatcher::return_to_prev_menu () { - if (_previously_active_menus.size () > 1) { - _previously_active_menus.pop_back (); - _focus_list.push_back (_previously_active_menus.back ()); +bool AccessibilityWatcher::returnToPrevMenu () { + if (previouslyActiveMenus.size () > 1) + { + previouslyActiveMenus.pop_back (); + focusList.push_back (previouslyActiveMenus.back ()); return true; } return false; @@ -437,128 +479,146 @@ AccessibilityWatcher::recurseFindCursor (AtspiAccessible* accessible) } return NULL; } - - -void AccessibilityWatcher::get_alternative_caret (FocusInfo& focus, const AtspiEvent* event) { +/* + * Tries to extrapolate a missing caret position from other text characters. + * is used as last resort when application doesn't respect at-spi standarts, + * or at-spi bugs. + */ +void AccessibilityWatcher::getAlternativeCaret (FocusInfo& focus, const AtspiEvent* event) { auto text = atspi_accessible_get_text (event->source); if (!text) { return; } auto offset = atspi_text_get_caret_offset (text, NULL); - auto caret_char = std::string (atspi_text_get_text_at_offset (text, offset, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content); - bool has_seen_17 = false; - if (caret_char == "\n" || caret_char == "\0") { // if we're at a newline, sometimes ATSPI doesn't feel like giving us a caret position. - int lines = 0; - if (atspi_text_get_character_count (text, NULL) == offset) { - lines++; // gives the last empty line the right focus. - } - int it = 1; - bool char_extents_found = false; + auto caretChar = std::string (atspi_text_get_string_at_offset (text, offset, ATSPI_TEXT_GRANULARITY_CHAR, NULL)->content); + bool hasSeenDeviceControl1 = false; + + // if we're at a newline, sometimes at-spi isn't giving us a caret position. unknown bug in some apps. + if (caretChar == "\n" || caretChar == "\0") + { + // gives the last empty line the right focus. + int lines = atspi_text_get_character_count (text, NULL) == offset ? 1 : 0; + int charIndex = 1; + bool charExtentsFound = false; + AtspiRect *size = atspi_text_get_character_extents (text, offset, ATSPI_COORD_TYPE_SCREEN, NULL); - while (!char_extents_found && it <= offset && it < 300) { // try and find the character on upper line to extrapolate from - size = atspi_text_get_character_extents (text, offset - it, ATSPI_COORD_TYPE_SCREEN, NULL); - caret_char = atspi_text_get_text_at_offset (text, offset -it, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content; - if ((size->x != 0 || size->y != 0) && int (caret_char[0]) != -17) { // if we found a caret, check we're at beginning of line (or of text) - if (offset -it -1 >= 0 && std::string (atspi_text_get_text_at_offset (text, offset -it -1, ATSPI_TEXT_BOUNDARY_CHAR, NULL)->content) == "\n") { - char_extents_found = true; // first character of upper line has been found - } else if (offset -it -1 == 0) { + // try and find the character on upper line to extrapolate position from. no more that 300 char, we risk lag. + while (!charExtentsFound && charIndex <= offset && charIndex < 300) { + size = atspi_text_get_character_extents (text, offset - charIndex, ATSPI_COORD_TYPE_SCREEN, NULL); + caretChar = atspi_text_get_string_at_offset (text, offset - charIndex, ATSPI_TEXT_GRANULARITY_CHAR, NULL)->content; + // if we found a caret, check we're at beginning of line (or of text) to extrapolate position + if ((size->x != 0 || size->y != 0) && int (caretChar[0]) != -17) + { + if (offset - charIndex -1 >= 0 && std::string (atspi_text_get_string_at_offset (text, offset - charIndex -1, ATSPI_TEXT_GRANULARITY_CHAR, NULL)->content) == "\n") + { + charExtentsFound = true; // first character of upper line has been found + } + else if (offset - charIndex -1 == 0) + { size = atspi_text_get_character_extents (text, 0, ATSPI_COORD_TYPE_SCREEN, NULL); - char_extents_found = true; // first character of upper line has been found + // first character of upper line has been found + charExtentsFound = true; } - } else if (caret_char == "\n" || int (caret_char[0]) == -17) { - lines ++; } - if (!has_seen_17 && int (caret_char[0]) == -17 ) { - has_seen_17 = true; + else if (caretChar == "\n" || int (caretChar[0]) == -17) + { + ++lines; + } + if (!hasSeenDeviceControl1 && int (caretChar[0]) == -17 ) + { + hasSeenDeviceControl1 = true; } - it ++; + ++charIndex; } - if (!has_seen_17) { + if (!hasSeenDeviceControl1) + { lines--; } - focus.x_alt = size->x; - focus.y_alt = size->y + (lines-1) * size->height; - focus.w_alt = size->width; - focus.h_alt = size->height; + focus.xAlt = size->x; + focus.yAlt = size->y + (lines-1) * size->height; + focus.wAlt = size->width; + focus.hAlt = size->height; } } -void AccessibilityWatcher::on_caret_move (const AtspiEvent *event, void *data) { - register_event (event, "caret"); +void AccessibilityWatcher::onCaretMove (const AtspiEvent *event, void *data) +{ + registerEvent (event, "caret"); } -void AccessibilityWatcher::on_selected_change (const AtspiEvent *event, void *data) { - register_event (event, "state-changed:selected"); +void AccessibilityWatcher::onSelectedChange (const AtspiEvent *event, void *data) +{ + registerEvent (event, "state-changed:selected"); } -void AccessibilityWatcher::on_focus (const AtspiEvent *event, void *data) { +void AccessibilityWatcher::onFocus (const AtspiEvent *event, void *data) { /* We only care about focus/selection gain * there's no detail1 on focus loss in AT-SPI specs */ if (!event->detail1) {return;} - register_event (event, "focus"); + registerEvent (event, "focus"); } -void AccessibilityWatcher::on_descendant_changed (const AtspiEvent *event, void *data) { - register_event (event, "active-descendant-changed"); +void AccessibilityWatcher::onDescendantChanged (const AtspiEvent *event, void *data) { + registerEvent (event, "active-descendant-changed"); } /* Register to events */ void AccessibilityWatcher::addWatches () { - listener = atspi_event_listener_new ((AtspiEventListenerCB)on_focus, NULL, NULL); - listener2 = atspi_event_listener_new ((AtspiEventListenerCB)on_caret_move, NULL, NULL); - listener3 = atspi_event_listener_new ((AtspiEventListenerCB)on_selected_change, NULL, NULL); - listener4 = atspi_event_listener_new ((AtspiEventListenerCB)on_descendant_changed, NULL, NULL); - - atspi_event_listener_register (listener, "object:state-changed:focused", NULL); - atspi_event_listener_register (listener2, "object:text-caret-moved", NULL); - atspi_event_listener_register (listener2, "object:text-changed:inserted", NULL); - atspi_event_listener_register (listener2, "object:text-changed:removed", NULL); - atspi_event_listener_register (listener3, "object:state-changed:selected", NULL); - atspi_event_listener_register (listener4, "object:active-descendant-changed", NULL); + focusListener = atspi_event_listener_new (reinterpret_cast (onFocus), NULL, NULL); + caretMoveListener = atspi_event_listener_new (reinterpret_cast (onCaretMove), NULL, NULL); + selectedListener = atspi_event_listener_new (reinterpret_cast (onSelectedChange), NULL, NULL); + descendantChangedListener = atspi_event_listener_new (reinterpret_cast (onDescendantChanged), NULL, NULL); + + atspi_event_listener_register (focusListener, "object:state-changed:focused", NULL); + atspi_event_listener_register (caretMoveListener, "object:text-caret-moved", NULL); + atspi_event_listener_register (caretMoveListener, "object:text-changed:inserted", NULL); + atspi_event_listener_register (caretMoveListener, "object:text-changed:removed", NULL); + atspi_event_listener_register (selectedListener, "object:state-changed:selected", NULL); + atspi_event_listener_register (descendantChangedListener, "object:active-descendant-changed", NULL); } void AccessibilityWatcher::removeWatches () { - atspi_event_listener_deregister (listener, "object:state-changed:focused", NULL); - atspi_event_listener_deregister (listener2, "object:text-caret-moved", NULL); - atspi_event_listener_deregister (listener2, "object:text-changed:inserted", NULL); - atspi_event_listener_deregister (listener2, "object:text-changed:removed", NULL); - atspi_event_listener_deregister (listener3, "object:state-changed:selected", NULL); - atspi_event_listener_deregister (listener4, "object:active-descendant-changed", NULL); + atspi_event_listener_deregister (focusListener, "object:state-changed:focused", NULL); + atspi_event_listener_deregister (caretMoveListener, "object:text-caret-moved", NULL); + atspi_event_listener_deregister (caretMoveListener, "object:text-changed:inserted", NULL); + atspi_event_listener_deregister (caretMoveListener, "object:text-changed:removed", NULL); + atspi_event_listener_deregister (selectedListener, "object:state-changed:selected", NULL); + atspi_event_listener_deregister (descendantChangedListener, "object:active-descendant-changed", NULL); } void AccessibilityWatcher::init () { - if (_initialized) { return; } + if (initialized) { return; } atspi_init (); atspi_set_main_context (g_main_context_default ()); addWatches (); - _initialized = true; + initialized = true; } void AccessibilityWatcher::setActive (bool activate) { - if (mActive && !activate) - { - removeWatches(); - } - else if (!mActive && activate) - { - addWatches(); - } + if (mActive && !activate) + { + removeWatches (); + } + else if (!mActive && activate) + { + addWatches (); + } } void AccessibilityWatcher::quit () { removeWatches (); - _initialized = false; + initialized = false; } -std::deque AccessibilityWatcher::get_focus_queue () { - return _focus_list; +std::deque AccessibilityWatcher::getFocusQueue () { + return focusList; } -void AccessibilityWatcher::reset_focus_queue () { - _focus_list.clear (); +void AccessibilityWatcher::resetFocusQueue () { + focusList.clear (); } diff --git a/plugins/focuspoll/src/focusinfo.cpp b/plugins/focuspoll/src/focusinfo.cpp new file mode 100644 index 000000000..4e345cac2 --- /dev/null +++ b/plugins/focuspoll/src/focusinfo.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2016 Auboyneau Vincent + * + * This file is part of compiz. + * + * this program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "focusinfo.h" + +FocusInfo::FocusInfo(const std::string& type, + const std::string& name, + const std::string& label, + const std::string& role, + const std::string& application, + int x, + int y, + int width, + int height) : + x(x), + y(y), + w(width), + h(height), + xAlt(0), + yAlt(0), + wAlt(0), + hAlt(0), + type(type), + name(name), + label(label), + role(role), + application(application), + enabled(false), + active(false), + focusable(false), + focused(false), + selected(false), + showing(false), + visible(false) { + }; + +FocusInfo::FocusInfo(const std::string& type, + const std::string& name, + const std::string& label, + const std::string& role, + const std::string& application) : + FocusInfo(type, + name, + label, + role, + application, + 0, 0, 0, 0) +{}; + +FocusInfo::FocusInfo() : FocusInfo("", "", "", "", "", 0, 0, 0, 0) {}; + +std::string +FocusInfo::FocusInfo::getType() +{ + return type; +}; + +std::tuple +FocusInfo::getPosition () +{ + return std::make_tuple(x, y); +}; + +std::tuple +FocusInfo::getSize () +{ + return std::make_tuple(w, h); +}; + +std::tuple +FocusInfo::getBBox () +{ + return std::make_tuple(x, y, w, h); +}; + +bool +FocusInfo::operator== (const FocusInfo& other) const +{ + return (other.x == x && + other.y == y && + other.w == w && + other.h == h && + other.type == type && + other.name == name && + other.label == label && + other.application == application && + other.role == role); +}; + +bool FocusInfo::operator!=(const FocusInfo& other) const +{ + return !(*this == other); +}; + +// TODO replace with op<< +std::string +FocusInfo::summary() +{ + std::ostringstream res; + res << "name:" << name; + res << " application:" << application; + res << " type:" << type; + if (label != "") {res << " label:" << label;} + res << " role:" << role; + res << " pos " << x << "," << y; + res << "(" << w << ":" << h << ")"; + res << "["; + if (active) {res << "active ";} + if (focused) {res << "focused ";} + if (selected) {res << "selected ";} + res << "]"; + + return res.str(); +} diff --git a/plugins/focuspoll/src/focuspoll.cpp b/plugins/focuspoll/src/focuspoll.cpp index 1598a61a1..79fe3991e 100644 --- a/plugins/focuspoll/src/focuspoll.cpp +++ b/plugins/focuspoll/src/focuspoll.cpp @@ -1,33 +1,32 @@ /* + * Copyright (C) 2016 Auboyneau Vincent * - * Compiz focus position polling plugin + * This file is part of compiz. * - * focuspoll.cpp + * this program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. * - * Copyright : (C) 2016 by Auboyneau vincent - * E-mail : ksamak@riseup.net - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . */ #include "private.h" COMPIZ_PLUGIN_20090315 (focuspoll, FocuspollPluginVTable); -bool FocuspollScreen::updatePosition () { - if (!a11ywatcher->get_focus_queue().empty()) { +bool +FocuspollScreen::updatePosition () +{ + if (!a11ywatcher->getFocusQueue().empty()) { int focusX, focusY, focusW, focusH; - std::tie(focusX, focusY, focusW, focusH) = a11ywatcher->get_focus_queue().back().getBBox(); + std::tie(focusX, focusY, focusW, focusH) = a11ywatcher->getFocusQueue().back().getBBox(); focusRect = CompRect(focusX, focusY, focusW, focusH); for (std::list::iterator it = pollers.begin (); it != pollers.end ();) { @@ -36,7 +35,7 @@ bool FocuspollScreen::updatePosition () { poller->mCallback(focusRect); } } - a11ywatcher->reset_focus_queue(); + a11ywatcher->resetFocusQueue(); return true; } @@ -46,7 +45,7 @@ FocuspollScreen::addTimer (FocusPoller *poller) bool start = pollers.empty (); std::list::iterator it = - std::find (pollers.begin (), pollers.end (), poller); + std::find (pollers.begin (), pollers.end (), poller); if (it != pollers.end ()) return false; @@ -78,6 +77,7 @@ FocuspollScreen::removeTimer (FocusPoller *poller) { a11ywatcher->setActive(false); timer.stop (); + } } void @@ -138,7 +138,6 @@ FocusPoller::stop () } mActive = false; - fs->removeTimer (this); } @@ -151,44 +150,55 @@ FocusPoller::active () FocusPoller::FocusPoller () : mActive (false), mCallback (NULL) { -} + } std::tuple FocuspollScreen::getScreenLimits() { - int x =0, y = 0; - for (auto dev : screen->outputDevs()) { - x = std::max(x, dev.x() + dev.width()); - y = std::max(y, dev.y() + dev.height()); - } - return std::make_tuple(x, y); + int x =0, y = 0; + for (auto dev : screen->outputDevs()) { + x = std::max(x, dev.x() + dev.width()); + y = std::max(y, dev.y() + dev.height()); + } + return std::make_tuple(x, y); } void -FocuspollScreen::updateTimer () // TODO straiten that coding style out lol +FocuspollScreen::updateTimer () { float timeout = optionGetFocusPollInterval (); timer.setTimes (timeout, timeout * 1.5); } -FocusPoller::~FocusPoller () { +FocusPoller::~FocusPoller () +{ if (mActive) { - stop(); + stop(); } } +void +FocuspollScreen::setOptions() +{ + a11ywatcher->setIgnoreLinks(optionGetIgnoreLinks()); +} + template class PluginClassHandler ; FocuspollScreen::FocuspollScreen (CompScreen *screen) : PluginClassHandler (screen) { - a11ywatcher = AccessibilityWatcher::get_instance(); + a11ywatcher = AccessibilityWatcher::getInstance(); a11ywatcher->init(); + int screenLimitX, screenLimitY; std::tie(screenLimitX, screenLimitY) = getScreenLimits(); a11ywatcher->setScreenLimits(screenLimitX, screenLimitY); + updateTimer (); timer.setCallback (boost::bind (&FocuspollScreen::updatePosition, this)); - optionSetFocusPollIntervalNotify (boost::bind (&FocuspollScreen::updateTimer, this)); + + optionSetIgnoreLinksNotify (boost::bind (&FocuspollScreen::setOptions, this)); + } bool diff --git a/plugins/focuspoll/src/private.h b/plugins/focuspoll/src/private.h index 601fb417e..b069b3497 100644 --- a/plugins/focuspoll/src/private.h +++ b/plugins/focuspoll/src/private.h @@ -1,23 +1,20 @@ /* + * Copyright (C) 2016 Auboyneau Vincent * - * Compiz focus position polling plugin + * This file is part of compiz. * - * focuspoll.cpp + * this program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. * - * Copyright : (C) 2016 by Auboyneau vincent - * E-mail : ksamak@riseup.net - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . */ #include @@ -48,6 +45,7 @@ class FocuspollScreen : std::list pollers; CompTimer timer; + CompTimer settingsTimer; CompRect focusRect; bool updatePosition (); @@ -58,7 +56,8 @@ class FocuspollScreen : private: AccessibilityWatcher* a11ywatcher; - std::tuple getScreenLimits(); + std::tuple getScreenLimits(); + void setOptions(); }; -- GitLab From e8327ed30bab9e514cf7b3bc1cac8c2470cfd887 Mon Sep 17 00:00:00 2001 From: ksamak Date: Wed, 31 May 2017 11:09:54 +0200 Subject: [PATCH 10/20] fix mouse lag in ezoom --- plugins/ezoom/src/ezoom.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/ezoom/src/ezoom.cpp b/plugins/ezoom/src/ezoom.cpp index 8f9fad397..0d8877e2b 100644 --- a/plugins/ezoom/src/ezoom.cpp +++ b/plugins/ezoom/src/ezoom.cpp @@ -1141,6 +1141,8 @@ EZoomScreen::updateMousePosition(const CompPoint &p) lastMouseChange = time(NULL); } } + cursorMoved (); + cScreen->damageScreen(); } void -- GitLab From a54b31055c1d598b775c2431c98e2cab39459595 Mon Sep 17 00:00:00 2001 From: ksamak Date: Tue, 6 Jun 2017 10:55:31 +0200 Subject: [PATCH 11/20] ezoom/showmouse: fixed plugin order priority --- plugins/ezoom/ezoom.xml.in | 1 + plugins/showmouse/showmouse.xml.in | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/ezoom/ezoom.xml.in b/plugins/ezoom/ezoom.xml.in index d3664ceac..ae09d7eae 100644 --- a/plugins/ezoom/ezoom.xml.in +++ b/plugins/ezoom/ezoom.xml.in @@ -8,6 +8,7 @@ decor mousepoll focuspoll + showmouse staticswitcher diff --git a/plugins/showmouse/showmouse.xml.in b/plugins/showmouse/showmouse.xml.in index 32e0d83e0..6c4efc3e0 100644 --- a/plugins/showmouse/showmouse.xml.in +++ b/plugins/showmouse/showmouse.xml.in @@ -11,9 +11,6 @@ cube decor - - ezoom - opengl mousepoll -- GitLab From b687a8e29af9f5df8deeb28776e17884395e6b93 Mon Sep 17 00:00:00 2001 From: ksamak Date: Fri, 9 Jun 2017 14:32:27 +0200 Subject: [PATCH 12/20] better lifecycle of atspi listeners --- plugins/focuspoll/src/accessibilitywatcher.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index d7c7ca80b..d4b976212 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -564,10 +564,13 @@ void AccessibilityWatcher::onDescendantChanged (const AtspiEvent *event, void *d /* Register to events */ void AccessibilityWatcher::addWatches () { - focusListener = atspi_event_listener_new (reinterpret_cast (onFocus), NULL, NULL); - caretMoveListener = atspi_event_listener_new (reinterpret_cast (onCaretMove), NULL, NULL); - selectedListener = atspi_event_listener_new (reinterpret_cast (onSelectedChange), NULL, NULL); - descendantChangedListener = atspi_event_listener_new (reinterpret_cast (onDescendantChanged), NULL, NULL); + if (!focusListener) + { + focusListener = atspi_event_listener_new (reinterpret_cast (onFocus), NULL, NULL); + caretMoveListener = atspi_event_listener_new (reinterpret_cast (onCaretMove), NULL, NULL); + selectedListener = atspi_event_listener_new (reinterpret_cast (onSelectedChange), NULL, NULL); + descendantChangedListener = atspi_event_listener_new (reinterpret_cast (onDescendantChanged), NULL, NULL); + } atspi_event_listener_register (focusListener, "object:state-changed:focused", NULL); atspi_event_listener_register (caretMoveListener, "object:text-caret-moved", NULL); @@ -611,6 +614,10 @@ AccessibilityWatcher::setActive (bool activate) void AccessibilityWatcher::quit () { removeWatches (); + g_object_unref (focusListener); + g_object_unref (caretMoveListener); + g_object_unref (selectedListener); + g_object_unref (descendantChangedListener); initialized = false; } -- GitLab From 02176bea8a0729168213b7667e1a251da1dcf96f Mon Sep 17 00:00:00 2001 From: ksamak Date: Fri, 9 Jun 2017 15:16:05 +0200 Subject: [PATCH 13/20] better lifecycle of atspi listeners --- plugins/focuspoll/src/accessibilitywatcher.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index d4b976212..f6c6cd38f 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -36,7 +36,11 @@ bool AccessibilityWatcher::ignoreLinks = false; AccessibilityWatcher::AccessibilityWatcher () : initialized (false), screenWidth (0), - screenHeight (0) + screenHeight (0), + focusListener (NULL), + caretMoveListener (NULL), + selectedListener (NULL), + descendantChangedListener (NULL), { } -- GitLab From 7515abe6f55fa0bff0539e59d20280ab1ffcdaba Mon Sep 17 00:00:00 2001 From: ksamak Date: Fri, 9 Jun 2017 15:41:12 +0200 Subject: [PATCH 14/20] fix google docs buggy alt caret focus --- .../focuspoll/src/accessibilitywatcher.cpp | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index f6c6cd38f..bbc3b1819 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -307,8 +307,9 @@ bool AccessibilityWatcher::appSpecificFilter (FocusInfo& focus, const AtspiEvent return true; } // assert whether we are inside a google document, then get kix caret - if (getBrowserURL (event->source).find ("docs.google") != std::string::npos && - AccessibilityWatcher::getKixCaret (focus, event)) + auto webAddress = getBrowserURL (event->source); + bool noAltCaret = webAddress.find ("docs.google") != std::string::npos; + if (noAltCaret && AccessibilityWatcher::getKixCaret (focus, event)) { AccessibilityWatcher::getInstance ()->focusList.push_back (focus); return true; @@ -318,18 +319,21 @@ bool AccessibilityWatcher::appSpecificFilter (FocusInfo& focus, const AtspiEvent AccessibilityWatcher::getInstance ()->focusList.push_back (focus); return true; } - getAlternativeCaret (focus, event); - if (focus.type == "caret" && - !(focus.xAlt == 0 && focus.yAlt == 0) && - !(focus.xAlt < AccessibilityWatcher::getInstance ()->screenWidth * -1 || focus.yAlt < AccessibilityWatcher::getInstance ()->screenHeight * -1) - ) + if (!noAltCaret) { - focus.x = focus.xAlt; - focus.y = focus.yAlt + focus.hAlt; - focus.w = focus.wAlt; - focus.h = focus.hAlt; - AccessibilityWatcher::getInstance ()->focusList.push_back (focus); - return true; + getAlternativeCaret (focus, event); + if (focus.type == "caret" && + !(focus.xAlt == 0 && focus.yAlt == 0) && + !(focus.xAlt < AccessibilityWatcher::getInstance ()->screenWidth * -1 || focus.yAlt < AccessibilityWatcher::getInstance ()->screenHeight * -1) + ) + { + focus.x = focus.xAlt; + focus.y = focus.yAlt + focus.hAlt; + focus.w = focus.wAlt; + focus.h = focus.hAlt; + AccessibilityWatcher::getInstance ()->focusList.push_back (focus); + return true; + } } } if (focus.application == "evince" && focus.type == "state-changed:selected" && focus.role == "icon") -- GitLab From f73845b83af43e1348d30d5b15c028f64a1c392d Mon Sep 17 00:00:00 2001 From: ksamak Date: Fri, 9 Jun 2017 16:38:14 +0200 Subject: [PATCH 15/20] add read-only mode to google docs --- .../accessibilitywatcher.h | 1 + .../focuspoll/src/accessibilitywatcher.cpp | 43 ++++++++++++++----- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h b/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h index e19e31d14..afb8721ec 100644 --- a/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h +++ b/plugins/focuspoll/include/accessibilitywatcher/accessibilitywatcher.h @@ -77,6 +77,7 @@ class AccessibilityWatcher { static std::string getBrowserURL(AtspiAccessible*); static bool getKixCaret (FocusInfo&, const AtspiEvent*); static AtspiAccessible* recurseFindCursor(AtspiAccessible*); + static AtspiAccessible* getChildFromVector(std::vector path, AtspiAccessible* startPoint); static void getAlternativeCaret(FocusInfo& focus, const AtspiEvent* event); static void onFocus(const AtspiEvent *event, void *data); diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index bbc3b1819..8cdf65598 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -314,7 +314,8 @@ bool AccessibilityWatcher::appSpecificFilter (FocusInfo& focus, const AtspiEvent AccessibilityWatcher::getInstance ()->focusList.push_back (focus); return true; } - if (focus.type == "caret" && !(focus.x == 0 && focus.y == 0)) + if (focus.type == "caret" && !(focus.x == 0 && focus.y == 0) && + !(focus.x < -2000 || focus.y < -2000)) { AccessibilityWatcher::getInstance ()->focusList.push_back (focus); return true; @@ -430,19 +431,22 @@ AccessibilityWatcher::getKixCaret (FocusInfo& focus, const AtspiEvent* event) g_object_unref (target); target = nextTarget; } - std::vector path {6, 0, 1, 4, 0, 1}; - for (auto childNb : path) + std::vector editPath {6, 0, 1, 4, 0, 1}; + std::vector readOnlyPath {6, 0, 1, 3, 0, 1}; + auto editChild = target; + auto readOnlyChild = target; + editChild = getChildFromVector(editPath, target); + readOnlyChild = getChildFromVector(readOnlyPath, target); + + auto recursedCursor = recurseFindCursor (editChild); + if (!recursedCursor) { - if (!target) - { - return false; - } - auto nextTarget = atspi_accessible_get_child_at_index (target, childNb, NULL); - g_object_unref (target); - target = nextTarget; + recursedCursor = recurseFindCursor (readOnlyChild); } - auto recursedCursor = recurseFindCursor (target); g_object_unref (target); + g_object_unref (editChild); + g_object_unref (readOnlyChild); + if (recursedCursor) { auto component = atspi_accessible_get_component (recursedCursor); if (component) @@ -460,6 +464,23 @@ AccessibilityWatcher::getKixCaret (FocusInfo& focus, const AtspiEvent* event) return false; } +AtspiAccessible* +AccessibilityWatcher::getChildFromVector(std::vector path, + AtspiAccessible* target) +{ + for (auto childNb : path) + { + if (!target) + { + return NULL; + } + auto nextTarget = atspi_accessible_get_child_at_index (target, childNb, NULL); + g_object_unref (target); + target = nextTarget; + } + return target; +} + /* * Recursively Finds a simulated kix cursor */ -- GitLab From 23576799a3eb935401ba9b4022fb179ed6d141d9 Mon Sep 17 00:00:00 2001 From: ksamak Date: Sun, 11 Jun 2017 20:45:23 +0200 Subject: [PATCH 16/20] comma mistake --- plugins/focuspoll/src/accessibilitywatcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index 8cdf65598..f8013b7ac 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -40,7 +40,7 @@ AccessibilityWatcher::AccessibilityWatcher () : focusListener (NULL), caretMoveListener (NULL), selectedListener (NULL), - descendantChangedListener (NULL), + descendantChangedListener (NULL) { } -- GitLab From 9c5d7f6647414844fbe4e8adf994ee9455adf0d5 Mon Sep 17 00:00:00 2001 From: ksamak Date: Tue, 13 Jun 2017 12:00:17 +0200 Subject: [PATCH 17/20] focuspoll: no alt caret for drive.google --- plugins/focuspoll/src/accessibilitywatcher.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index f8013b7ac..592f2baff 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -308,7 +308,8 @@ bool AccessibilityWatcher::appSpecificFilter (FocusInfo& focus, const AtspiEvent } // assert whether we are inside a google document, then get kix caret auto webAddress = getBrowserURL (event->source); - bool noAltCaret = webAddress.find ("docs.google") != std::string::npos; + bool noAltCaret = (webAddress.find ("docs.google") != std::string::npos || + webAddress.find ("drive.google") != std::string::npos); if (noAltCaret && AccessibilityWatcher::getKixCaret (focus, event)) { AccessibilityWatcher::getInstance ()->focusList.push_back (focus); -- GitLab From 9caa928e22c3661f1d1b916e832b58b9955e233a Mon Sep 17 00:00:00 2001 From: ksamak Date: Fri, 23 Jun 2017 10:41:05 +0200 Subject: [PATCH 18/20] better lifecycle of gobject atspiRelations --- plugins/focuspoll/src/accessibilitywatcher.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index 592f2baff..7493e8a06 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -66,6 +66,8 @@ std::string AccessibilityWatcher::getLabel (AtspiAccessible *accessible) { AtspiRelation *relation; for (unsigned i = 0; i < relations->len; ++i) { relation = g_array_index (relations, AtspiRelation*, i); + if (relation == NULL) + continue if (atspi_relation_get_relation_type (relation) == ATSPI_RELATION_LABELLED_BY) { g_array_free (relations, true); @@ -74,11 +76,10 @@ std::string AccessibilityWatcher::getLabel (AtspiAccessible *accessible) { g_object_unref (relation); return (res_label == NULL) ? "" : res_label; } + g_object_unref (relation); } - if (relations->len > 0) - { - g_object_unref (relations); - } + g_array_free (relations, true); + g_object_unref (relations); return ""; } -- GitLab From 094f1e65a7e5f07e5367fc96eb1d2aa5c8568931 Mon Sep 17 00:00:00 2001 From: ksamak Date: Fri, 23 Jun 2017 11:40:36 +0200 Subject: [PATCH 19/20] typo fix --- plugins/focuspoll/src/accessibilitywatcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/focuspoll/src/accessibilitywatcher.cpp b/plugins/focuspoll/src/accessibilitywatcher.cpp index 7493e8a06..46b78f79c 100644 --- a/plugins/focuspoll/src/accessibilitywatcher.cpp +++ b/plugins/focuspoll/src/accessibilitywatcher.cpp @@ -67,7 +67,7 @@ std::string AccessibilityWatcher::getLabel (AtspiAccessible *accessible) { for (unsigned i = 0; i < relations->len; ++i) { relation = g_array_index (relations, AtspiRelation*, i); if (relation == NULL) - continue + continue; if (atspi_relation_get_relation_type (relation) == ATSPI_RELATION_LABELLED_BY) { g_array_free (relations, true); -- GitLab From 4afe14aac30b3011ca88b7cf7b6d512a8d9365ef Mon Sep 17 00:00:00 2001 From: Cyril Brulebois Date: Thu, 29 Jun 2017 11:18:23 +0200 Subject: [PATCH 20/20] releasing version 2:0.9.12.2+hypra7.5 --- debian/changelog | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index d92a4817f..5739b78c7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,9 @@ -compiz (2:0.9.12.2+hypra7.5) UNRELEASED; urgency=medium +compiz (2:0.9.12.2+hypra7.5) jessie; urgency=medium + [ ksamak ] * added focuspoll plugin - -- ksamak Wed, 24 May 2017 12:09:10 +0200 + -- Cyril Brulebois Thu, 29 Jun 2017 11:13:16 +0200 compiz (2:0.9.12.2+hypra7.4) jessie; urgency=medium -- GitLab