From a50e4af333979ec5f5b86a0ad2922dc2736a5d4b Mon Sep 17 00:00:00 2001 From: ksamak Date: Fri, 21 Jul 2017 10:17:08 +0200 Subject: [PATCH] merged modifs from stretch for gdocs --- plugins/ezoom/ezoom.xml.in | 206 +++- plugins/ezoom/src/ezoom.cpp | 163 +++- plugins/ezoom/src/ezoom.h | 19 +- plugins/focuspoll/focuspoll.xml.in | 14 +- .../accessibilitywatcher.h | 106 +- .../include/accessibilitywatcher/focusinfo.h | 170 ++-- .../focuspoll/include/focuspoll/focuspoll.h | 49 +- .../focuspoll/src/accessibilitywatcher.cpp | 910 +++++++++++------- plugins/focuspoll/src/focusinfo.cpp | 130 +++ plugins/focuspoll/src/focuspoll.cpp | 109 ++- plugins/focuspoll/src/private.h | 33 +- plugins/mousepoll/CMakeLists.txt | 4 + .../mousepoll/include/mousepoll/mousepoll.h | 6 +- plugins/mousepoll/src/mousepoll.cpp | 49 +- plugins/mousepoll/src/private.h | 4 +- 15 files changed, 1274 insertions(+), 698 deletions(-) mode change 100644 => 100755 plugins/ezoom/ezoom.xml.in mode change 100644 => 100755 plugins/ezoom/src/ezoom.cpp mode change 100644 => 100755 plugins/ezoom/src/ezoom.h create mode 100644 plugins/focuspoll/src/focusinfo.cpp diff --git a/plugins/ezoom/ezoom.xml.in b/plugins/ezoom/ezoom.xml.in old mode 100644 new mode 100755 index d3664ceac..123d44dfd --- a/plugins/ezoom/ezoom.xml.in +++ b/plugins/ezoom/ezoom.xml.in @@ -8,6 +8,7 @@ decor mousepoll focuspoll + showmouse staticswitcher @@ -90,49 +91,218 @@ 1 50 + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/ezoom/src/ezoom.cpp b/plugins/ezoom/src/ezoom.cpp old mode 100644 new mode 100755 index 19d7279a3..7c7fafe1e --- a/plugins/ezoom/src/ezoom.cpp +++ b/plugins/ezoom/src/ezoom.cpp @@ -1123,26 +1123,26 @@ 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); + } + } + cursorMoved (); + cScreen->damageScreen(); } void @@ -1164,7 +1164,6 @@ EZoomScreen::updateFocusPosition(const CompRect &rect) _non_mouse_focus_tracking = true; lastFocusChange = time(NULL); } - cursorMoved(); cScreen->damageScreen(); } @@ -1658,16 +1657,68 @@ EZoomScreen::zoomSpecific (CompAction *action, switch (target) { - case ZoomTargetFirst: - zoom_level = optionGetZoomSpec1 (); + case ZoomTarget1: + zoom_level = optionGetZoomSpecific1 (); + break; + + case ZoomTarget2: + zoom_level = optionGetZoomSpecific2 (); + break; + + case ZoomTarget3: + zoom_level = optionGetZoomSpecific3 (); + break; + + case ZoomTarget4: + zoom_level = optionGetZoomSpecific4 (); + break; + + case ZoomTarget5: + zoom_level = optionGetZoomSpecific5 (); + break; + + case ZoomTarget6: + zoom_level = optionGetZoomSpecific6 (); + break; + + case ZoomTarget7: + zoom_level = optionGetZoomSpecific7 (); + break; + + case ZoomTarget8: + zoom_level = optionGetZoomSpecific8 (); + break; + + case ZoomTarget9: + zoom_level = optionGetZoomSpecific9 (); + break; + + case ZoomTarget10: + zoom_level = optionGetZoomSpecific10 (); + break; + + case ZoomTarget11: + zoom_level = optionGetZoomSpecific11 (); + break; + + case ZoomTarget12: + zoom_level = optionGetZoomSpecific12 (); + break; + + case ZoomTarget13: + zoom_level = optionGetZoomSpecific13 (); + break; + + case ZoomTarget14: + zoom_level = optionGetZoomSpecific14 (); break; - case ZoomTargetSecond: - zoom_level = optionGetZoomSpec2 (); + case ZoomTarget15: + zoom_level = optionGetZoomSpecific15 (); break; - case ZoomTargetThird: - zoom_level = optionGetZoomSpec3 (); + case ZoomTarget16: + zoom_level = optionGetZoomSpecific16 (); break; default: @@ -2035,16 +2086,54 @@ EZoomScreen::EZoomScreen (CompScreen *screen) : optionSetZoomOutKeyInitiate (boost::bind (&EZoomScreen::zoomOut, this, _1, _2, _3)); - optionSetZoomSpecific1KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, - this, _1, _2, _3, - ZoomTargetFirst)); - optionSetZoomSpecific2KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, - this, _1, _2, _3, - ZoomTargetSecond)); - optionSetZoomSpecific3KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, - this, _1, _2, _3, - ZoomTargetThird)); - + optionSetZoomSpecific1KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget1)); + optionSetZoomSpecific2KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget2)); + optionSetZoomSpecific3KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget3)); + optionSetZoomSpecific4KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget4)); + optionSetZoomSpecific5KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget5)); + optionSetZoomSpecific6KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget6)); + optionSetZoomSpecific7KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget7)); + optionSetZoomSpecific8KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget8)); + optionSetZoomSpecific9KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget9)); + optionSetZoomSpecific10KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget10)); + optionSetZoomSpecific11KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget11)); + optionSetZoomSpecific12KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget12)); + optionSetZoomSpecific13KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget13)); + optionSetZoomSpecific14KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget14)); + optionSetZoomSpecific15KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget15)); + optionSetZoomSpecific16KeyInitiate (boost::bind (&EZoomScreen::zoomSpecific, + this, _1, _2, _3, + ZoomTarget16)); optionSetPanLeftKeyInitiate (boost::bind (&EZoomScreen::zoomPan, this, _1, _2, _3, -1, 0)); optionSetPanRightKeyInitiate (boost::bind (&EZoomScreen::zoomPan, this, _1, diff --git a/plugins/ezoom/src/ezoom.h b/plugins/ezoom/src/ezoom.h old mode 100644 new mode 100755 index baf987f0a..62f4ce4c3 --- a/plugins/ezoom/src/ezoom.h +++ b/plugins/ezoom/src/ezoom.h @@ -51,9 +51,22 @@ enum SpecificZoomTarget { - ZoomTargetFirst = 0, - ZoomTargetSecond, - ZoomTargetThird + ZoomTarget1 = 0, + ZoomTarget2, + ZoomTarget3, + ZoomTarget4, + ZoomTarget5, + ZoomTarget6, + ZoomTarget7, + ZoomTarget8, + ZoomTarget9, + ZoomTarget10, + ZoomTarget11, + ZoomTarget12, + ZoomTarget13, + ZoomTarget14, + ZoomTarget15, + ZoomTarget16 }; class EZoomScreen : 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 a81489d0b..afb8721ec 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,56 +29,61 @@ class AccessibilityWatcher { public: - static AccessibilityWatcher* get_instance(); - ~AccessibilityWatcher() {quit();}; - - void init(); - void quit(); + ~AccessibilityWatcher(); + static AccessibilityWatcher* getInstance(); - void setIgnoreLinks(bool); - void setScreenLimits(int, int); + void init(); + void quit(); + void setActive (bool); - 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; - - // screen vars - static Display* dpy; - - bool _initialized; - 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); - 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); - - AtspiEventListener *listener, *listener2, *listener3, *listener4; + AccessibilityWatcher(); + static AccessibilityWatcher* instance; + + bool initialized; + bool mActive; + 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 AtspiAccessible* getChildFromVector(std::vector path, AtspiAccessible* startPoint); + static void getAlternativeCaret(FocusInfo& focus, const AtspiEvent* event); + + 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 4de21f121..52eb16661 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,427 +25,652 @@ #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() : - screenWidth(0), - screenHeight(0), - _initialized(false) +AccessibilityWatcher* AccessibilityWatcher::instance = NULL; +bool AccessibilityWatcher::ignoreLinks = false; + +AccessibilityWatcher::AccessibilityWatcher () : + initialized (false), + screenWidth (0), + screenHeight (0), + focusListener (NULL), + caretMoveListener (NULL), + selectedListener (NULL), + descendantChangedListener (NULL) { } -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) { - return ""; +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++) { - 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); - } + 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) + { + auto res_label = atspi_accessible_get_name (atspi_relation_get_target (relation, 0), NULL); + g_object_unref (relation); + g_array_free (relations, true); + return (res_label == NULL) ? "" : res_label; + } + g_object_unref (relation); } + g_array_free (relations, true); return ""; } -void AccessibilityWatcher::setIgnoreLinks(bool val) { - _ignore_links = val; -} - -void AccessibilityWatcher::setScreenLimits(int x, int y) { - screenWidth = x; - 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; +void AccessibilityWatcher::setIgnoreLinks (bool val) { + ignoreLinks = val; } -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; +void AccessibilityWatcher::setScreenLimits (int x, int y) { + screenWidth = x; + screenHeight = y; } -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); +int AccessibilityWatcher::getScreenWidth () { + return screenWidth; } -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; - } +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); +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)); - 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); + 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; + } + g_object_unref (parent); } 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); + 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); + 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; + 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") { - 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; - } + if (type == "caret") + { + auto text = atspi_accessible_get_text (event->source); + if (!text) + { + return; + } + auto offset = atspi_text_get_caret_offset (text, NULL); + // 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; + } + // 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; + } + // 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" && 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; + } + } + 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)) { - res.focused = true; - AccessibilityWatcher::get_instance()->_previously_active_menus.clear(); // reset potential menu stack + auto stateSet = atspi_accessible_get_state_set (event->source); + if (atspi_state_set_contains (stateSet, ATSPI_STATE_FOCUSED)) + { + res.focused = true; + // reset potential menu stack + AccessibilityWatcher::getInstance ()->previouslyActiveMenus.clear (); } - if (atspi_state_set_contains(state_set, ATSPI_STATE_SELECTED)) { // never works, GTK Bad implem? - res.selected = true; + 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) { - res.selected = true; - AccessibilityWatcher::get_instance()->_previously_active_menus.push_back(res); // add to stack of menus + if (res.type == "state-changed:selected" && event->detail1 == 1) + { + res.selected = true; + // add to stack of menus + AccessibilityWatcher::getInstance ()->previouslyActiveMenus.push_back (res); } - if (app_specific_filter(res, event)) { - return; + if (appSpecificFilter (res, event)) + { + return; } - if (filter_bad_events(res)) { - return; + 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" || - 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::getInstance ()->returnToPrevMenu ()) + { + 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 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.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; - } - } - 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.application == "Firefox") { - if (_ignore_links && focus.type != "caret" && focus.role == "link") { - return true; - } - 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 - return true; - } - if (focus.type == "focus" && focus.role == "document frame") { // general page parasite event - return true; - } - if (focus.type == "caret" && !(focus.x == 0 && focus.y == 0)) { - AccessibilityWatcher::get_instance()->_focus_list.push_back(focus); - return true; - } - get_alternative_caret(focus, event); - if (focus.type == "caret" && !(focus.x_alt == 0 && focus.y_alt == 0)) { - 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 + 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 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::getInstance ()->focusList.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::getInstance ()->focusList.push_back (focus); + return true; + } + } + } + if (focus.application == "Firefox") + { + if (ignoreLinks && 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; + } + // prevents status bar focus in firefox + if (focus.type == "caret" && + (focus.name == "Search or enter address")) { + return true; + } + 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 + auto webAddress = getBrowserURL (event->source); + 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); + return true; + } + if (focus.type == "caret" && !(focus.x == 0 && focus.y == 0) && + !(focus.x < -2000 || focus.y < -2000)) + { + AccessibilityWatcher::getInstance ()->focusList.push_back (focus); + return true; + } + if (!noAltCaret) + { + 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") + { // 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) { - return true; +bool AccessibilityWatcher::filterBadEvents (const FocusInfo& event) { + if (event.type == "caret" && event.x ==0 && event.y == 0) + { + return true; } - if (!event.active) { - return true; + if (!event.active) + { + return true; } - if (!event.focused && !event.selected) { - return true; + 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 - event.x < 0 || - event.y < 0 )) { - return true; + 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; } return false; } +std::string +AccessibilityWatcher::getBrowserURL (AtspiAccessible* accessible) +{ + if (!accessible) + return ""; + + 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 ""; +} + + /* * 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()); - return true; - } - return false; +bool AccessibilityWatcher::returnToPrevMenu () { + if (previouslyActiveMenus.size () > 1) + { + previouslyActiveMenus.pop_back (); + focusList.push_back (previouslyActiveMenus.back ()); + return true; + } + 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) +{ + auto target = event->source; + for (int i = 0; i < 5; ++i) + { + if (!target) + { + return false; + } + auto nextTarget = atspi_accessible_get_parent (target, NULL); + g_object_unref (target); + target = nextTarget; + } + if (!target) + { + return false; + } + + AtspiAccessible *recursedCursor = NULL; + std::vector> optimizedPaths { + {0, 0, 7, 0, 1, 4, 0, 1}, // path towards a text-changed:insert actual object + {0, 7, 0, 1, 4, 0, 1}, // path towards a text-changed:insert actual object + {0, 6, 0, 1, 3, 0, 1}, // path towards a text-caret-moved actual object + {0, 0, 6, 0, 1, 3, 0, 1}, // path towards a text-caret moved in read-only + }; + for (auto path : optimizedPaths) + { + auto targetChild = getChildFromVector(path, target); + if (targetChild) + { + recursedCursor = recurseFindCursor (targetChild); + g_object_unref (targetChild); + } + 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); + g_object_unref (recursedCursor); + return true; + } + g_object_unref (recursedCursor); + } + } + 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; } -void AccessibilityWatcher::get_alternative_caret(FocusInfo& focus, const AtspiEvent* event) { - auto text = atspi_accessible_get_text(event->source); +/* + * 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) + { + if (std::string ((gchar*)class_atr).find ("kix-cursor-caret") != std::string::npos) + { + g_hash_table_destroy (attributes); + return accessible; + } + } + 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)); + if (match) + { + return match; + } + } + return NULL; +} +/* + * 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; - 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; + auto offset = atspi_text_get_caret_offset (text, NULL); + 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); + // 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); + // first character of upper line has been found + charExtentsFound = true; + } + } + else if (caretChar == "\n" || int (caretChar[0]) == -17) + { + ++lines; + } + if (!hasSeenDeviceControl1 && int (caretChar[0]) == -17 ) + { + hasSeenDeviceControl1 = true; + } + ++charIndex; + } + if (!hasSeenDeviceControl1) + { + lines--; + } + 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); +void AccessibilityWatcher::addWatches () { + 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); + atspi_event_listener_register (caretMoveListener, "object:text-changed:inserted", NULL); // deprecation in stretch? + atspi_event_listener_register (caretMoveListener, "object:text-changed:insert", NULL); + atspi_event_listener_register (caretMoveListener, "object:text-changed:removed", NULL); + atspi_event_listener_register (selectedListener, "object:text-selection-changed", 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); +void AccessibilityWatcher::removeWatches () { + 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:insert", NULL); + atspi_event_listener_deregister (caretMoveListener, "object:text-changed:removed", NULL); + atspi_event_listener_deregister (selectedListener, "object:text-selection-changed", NULL); + atspi_event_listener_deregister (selectedListener, "object:state-changed:selected", NULL); // deprecation in stretch? + atspi_event_listener_deregister (descendantChangedListener, "object:active-descendant-changed", NULL); } -void AccessibilityWatcher::init() { - if (_initialized) { return; } +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; +} - _initialized = true; +void +AccessibilityWatcher::setActive (bool activate) +{ + if (mActive && !activate) + { + removeWatches (); + } + else if (!mActive && activate) + { + addWatches (); + } } -void AccessibilityWatcher::quit() { - removeWatches(); - _initialized = false; +void AccessibilityWatcher::quit () { + removeWatches (); + g_object_unref (focusListener); + g_object_unref (caretMoveListener); + g_object_unref (selectedListener); + g_object_unref (descendantChangedListener); + 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 c27a1974e..73918d475 100644 --- a/plugins/focuspoll/src/focuspoll.cpp +++ b/plugins/focuspoll/src/focuspoll.cpp @@ -1,39 +1,41 @@ /* + * 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()) { - 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); - } +bool +FocuspollScreen::updatePosition () +{ + if (!a11ywatcher->getFocusQueue().empty()) { + int focusX, focusY, focusW, focusH; + std::tie(focusX, focusY, focusW, focusH) = a11ywatcher->getFocusQueue().back().getBBox(); + focusRect = CompRect(focusX, focusY, focusW, focusH); + std::list::iterator it; + for (it = pollers.begin (); it != pollers.end ();) + { + FocusPoller *poller = *it; + ++it; + poller->mCallback(focusRect); + } } - a11ywatcher->reset_focus_queue(); return true; } @@ -43,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; @@ -53,6 +55,7 @@ FocuspollScreen::addTimer (FocusPoller *poller) if (start) { //focusHasMoved(); + a11ywatcher->setActive(true); timer.start(); } @@ -71,7 +74,10 @@ FocuspollScreen::removeTimer (FocusPoller *poller) pollers.erase (it); if (pollers.empty ()) + { + a11ywatcher->setActive(false); timer.stop (); + } } void @@ -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, @@ -132,8 +138,7 @@ FocusPoller::stop () } mActive = false; - - ms->removeTimer (this); + fs->removeTimer (this); } bool @@ -145,47 +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) { - std::cout << "starting focuspoll" << std::endl; - a11ywatcher = AccessibilityWatcher::get_instance(); + a11ywatcher = AccessibilityWatcher::getInstance(); 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)); + + optionSetIgnoreLinksNotify (boost::bind (&FocuspollScreen::setOptions, this)); + } bool diff --git a/plugins/focuspoll/src/private.h b/plugins/focuspoll/src/private.h index 60f5a8a90..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,12 +56,13 @@ class FocuspollScreen : private: AccessibilityWatcher* a11ywatcher; - std::tuple getScreenLimits(); + std::tuple getScreenLimits(); + void setOptions(); }; #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