├── .eslintrc.json ├── .github └── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── feature-request.md │ └── missing-device.md ├── .gitignore ├── COPYING ├── Makefile ├── README.md ├── Settings.ui ├── extension.js ├── lib.js ├── lint ├── eslintrc-gjs.json ├── eslintrc-legacy.json ├── eslintrc-shell.json └── generate-report.sh ├── locale ├── hi │ └── LC_MESSAGES │ │ ├── touchpad-indicator.mo │ │ └── touchpad-indicator.po └── touchpad-indicator.pot ├── media ├── Screenshot from 2019-07-01 14-41-27.png ├── Screenshot from 2019-07-01 14-52-06.png ├── Screenshot from 2019-07-01 14-52-23.png ├── Screenshot from 2019-07-01 15-30-35.png └── screenshots.gif ├── metadata.json ├── prefs.js ├── schemas ├── gschemas.compiled └── org.gnome.shell.extensions.touchpad-indicator.gschema.xml ├── synclient.js └── xinput.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "./lint/eslintrc-gjs.json", 4 | "./lint/eslintrc-shell.json" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report an issue with touchpad-indicator@orangeshirt Gnome Shell extension 4 | title: A very very short summary of the issue 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the issue** 11 | A clear and concise description of what the issue is. 12 | 13 | 14 | --- 15 | **Expected behavior** 16 | A clear and concise description of what you expected to happen. 17 | 18 | 19 | --- 20 | **Steps to reproduce the behavior** 21 | 1. Go to '...' 22 | 2. Click on '....' 23 | 3. Scroll down to '....' 24 | 4. See error 25 | 26 | 27 | --- 28 | **Screenshots** (if required, add screenshots to help explain your problem) 29 | 30 | 31 | --- 32 | **Mandatory system details** (please complete/update the following information) 33 | - **Operating System:** Fedora 31 (Workstation Edition) 34 | - **Touchpad Indicator extension version:** 34 35 | - **Gnome Shell version:** GNOME Shell 3.34.5 36 | - **Display server:** X11 or Wayland 37 | - **Switching method:** GSetting or Xinput or Synclient 38 | - **Installation source:** [extensions.gnome.org](https://extensions.gnome.org/extension/131/touchpad-indicator/) or [GitHub repository](https://github.com/user501254/TouchpadIndicator) 39 | 40 | 41 | --- 42 | **Optional details** (mandatory if you are reporting issues with device detection, switch functionality) 43 | 44 | - **Input Devices** (ie. output for `cat /proc/bus/input/devices`) 45 | ``` 46 | I: Bus=0019 Vendor=0000 Product=0005 Version=0000 47 | N: Name="Lid Switch" 48 | P: Phys=PNP0C0D/button/input0 49 | S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/input/input0 50 | U: Uniq= 51 | H: Handlers=event0 52 | B: PROP=0 53 | B: EV=21 54 | B: SW=1 55 | 56 | . 57 | . 58 | . 59 | . 60 | ``` 61 | 62 | - **X input devices** (ie. output for `xinput list`) 63 | ``` 64 | ⎡ Virtual core pointer id=2 [master pointer (3)] 65 | ⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)] 66 | ⎜ ↳ DLL096D:01 06CB:CDE6 Touchpad id=12 [slave pointer (2)] 67 | ⎜ ↳ Logitech B330/M330/M3 id=9 [slave pointer (2)] 68 | ⎣ Virtual core keyboard id=3 [master keyboard (2)] 69 | ↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)] 70 | ↳ Video Bus id=6 [slave keyboard (3)] 71 | ↳ Power Button id=7 [slave keyboard (3)] 72 | ↳ Sleep Button id=8 [slave keyboard (3)] 73 | ↳ Integrated_Webcam_HD: Integrate id=10 [slave keyboard (3)] 74 | ↳ Integrated_Webcam_HD: Integrate id=11 [slave keyboard (3)] 75 | ↳ Intel HID events id=13 [slave keyboard (3)] 76 | ↳ Intel HID 5 button array id=14 [slave keyboard (3)] 77 | ↳ Dell WMI hotkeys id=15 [slave keyboard (3)] 78 | ↳ AT Translated Set 2 keyboard id=16 [slave keyboard (3)] 79 | ↳ Mi Sports BT Earphones Basic (AVRCP) id=19 [slave keyboard (3)] 80 | ↳ Logitech B330/M330/M3 id=17 [slave keyboard (3)] 81 | ``` 82 | 83 | - Log file (you can enable logging within the extension settings, "Debug" tab) 84 | Please upload the log file `$HOME/.local/share/gnome-shell/extensions/touchpad-indicator@orangeshirt/touchpad-indicator.log` 85 | 86 | 87 | --- 88 | **Additional context** 89 | Add any other context about the problem here. 90 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an enhancement for touchpad-indicator@orangeshirt Gnome Shell extension 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/missing-device.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Missing device 3 | about: Report missing input device type/string 4 | title: Missing device of type touchscreen/trackpad/pen/etc 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | This extension relies on the output of `cat /proc/bus/input/devices` and string matching to determine the input device type (ie. touchpad, trackpoint, touchscreen, fingertouch, pen). 11 | 12 | In case you have a device of a particular type and it's not recognized by the extension, please provide/update the below details. 13 | 14 | Additionally, you may create a [pull-request](https://github.com/user501254/TouchpadIndicator/pulls) by updating the required strings at https://github.com/user501254/TouchpadIndicator/blob/master/lib.js#L41-L45. 15 | 16 | --- 17 | - **Product page or name of the device** (optional): eg. https://www.logitech.com/en-us/product/mx-master-3 18 | 19 | - **Input Devices** (ie. output for `cat /proc/bus/input/devices`) 20 | ``` 21 | I: Bus=0019 Vendor=0000 Product=0005 Version=0000 22 | N: Name="Lid Switch" 23 | P: Phys=PNP0C0D/button/input0 24 | S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/input/input0 25 | U: Uniq= 26 | H: Handlers=event0 27 | B: PROP=0 28 | B: EV=21 29 | B: SW=1 30 | 31 | . 32 | . 33 | . 34 | . 35 | ``` 36 | 37 | - **X input devices** (ie. output for `xinput list`) 38 | ``` 39 | ⎡ Virtual core pointer id=2 [master pointer (3)] 40 | ⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)] 41 | ⎜ ↳ DLL096D:01 06CB:CDE6 Touchpad id=12 [slave pointer (2)] 42 | ⎜ ↳ Logitech B330/M330/M3 id=9 [slave pointer (2)] 43 | ⎣ Virtual core keyboard id=3 [master keyboard (2)] 44 | ↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)] 45 | ↳ Video Bus id=6 [slave keyboard (3)] 46 | ↳ Power Button id=7 [slave keyboard (3)] 47 | ↳ Sleep Button id=8 [slave keyboard (3)] 48 | ↳ Integrated_Webcam_HD: Integrate id=10 [slave keyboard (3)] 49 | ↳ Integrated_Webcam_HD: Integrate id=11 [slave keyboard (3)] 50 | ↳ Intel HID events id=13 [slave keyboard (3)] 51 | ↳ Intel HID 5 button array id=14 [slave keyboard (3)] 52 | ↳ Dell WMI hotkeys id=15 [slave keyboard (3)] 53 | ↳ AT Translated Set 2 keyboard id=16 [slave keyboard (3)] 54 | ↳ Mi Sports BT Earphones Basic (AVRCP) id=19 [slave keyboard (3)] 55 | ↳ Logitech B330/M330/M3 id=17 [slave keyboard (3)] 56 | ``` 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/linux 3 | # Edit at https://www.gitignore.io/?templates=linux 4 | 5 | ### Linux ### 6 | *~ 7 | 8 | # temporary files which can be created if a process still has a handle open of a deleted file 9 | .fuse_hidden* 10 | 11 | # KDE directory preferences 12 | .directory 13 | 14 | # Linux trash folder which might appear on any partition or disk 15 | .Trash-* 16 | 17 | # .nfs files are created when an open file is removed but is still being accessed 18 | .nfs* 19 | 20 | # End of https://www.gitignore.io/api/linux 21 | 22 | # log file 23 | touchpad-indicator.log -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PACKAGE=touchpad-indicator 2 | 3 | GETTEXT_PACKAGE = $(PACKAGE) 4 | UUID = $(PACKAGE)@orangeshirt 5 | 6 | DOC_FILES=README.md COPYING 7 | SRC_FILES=extension.js prefs.js lib.js synclient.js xinput.js Settings.ui 8 | MO_FILE=hi/LC_MESSAGES/$(GETTEXT_PACKAGE).mo 9 | SCHEMA_FILES=schemas/gschemas.compiled schemas/org.gnome.shell.extensions.touchpad-indicator.gschema.xml 10 | EXTENSION_FILES=metadata.json 11 | OUTPUT=$(DOC_FILES) $(SRC_FILES) $(MO_FILES) $(SCHEMA_FILES) $(EXTENSION_FILES) 12 | POT_FILE=hi/$(GETTEXT_PACKAGE).pot 13 | LOCAL_INSTALL=~/.local/share/gnome-shell/extensions/$(UUID) 14 | 15 | .PHONY: pack update-po install enable disable reload help 16 | 17 | pack: $(OUTPUT) ## Pack sources for install. 18 | zip $(UUID).zip $(OUTPUT) 19 | 20 | $(POT_FILE): $(SRC_FILES) ## generate gettext pot file. 21 | mkdir -p po 22 | xgettext -d $(GETTEXT_PACKAGE) -o $@ $(SRC_FILES) --from-code=UTF-8 23 | 24 | update-po: $(POT_FILE) ## Update gettext po files. 25 | for lang in $(LANGUAGES); do \ 26 | msgmerge -U po/$$lang.po $(POT_FILE); \ 27 | done 28 | 29 | locale/%/LC_MESSAGES/$(PACKAGE).mo: po/%.po ## Generate gettext-compiled mo file. 30 | mkdir -p `dirname $@` 31 | msgfmt $< -o $@ 32 | 33 | schemas/gschemas.compiled: schemas/org.gnome.shell.extensions.touchpad-indicator.gschema.xml ## Compile gschemas. 34 | glib-compile-schemas schemas 35 | 36 | install: pack ## Install extension in user space. 37 | mkdir -p $(LOCAL_INSTALL) 38 | rm -rf $(LOCAL_INSTALL) 39 | unzip $(UUID).zip -d $(LOCAL_INSTALL) 40 | 41 | enable: ## Enable extension in gnome-shell. 42 | gnome-extensions enable $(UUID) 43 | 44 | disable: ## Disable extension in gnome-shell. 45 | gnome-extensions disable $(UUID) 46 | 47 | reload: ## Reload extension. 48 | gnome-extensions reset $(UUID) 49 | 50 | help: ## Show this help. 51 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-30s\033[0m %s\n", $$1, $$2}' 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TouchpadIndicator 2 | Touchpad management GNOME Shell Extension. 3 | 4 | Automatically disable other pointing devices when an external mouse is plugged in. 5 | Optionally, switch the touchpad, trackpoint, fingertouch, touchscreen or a pen device on and off easily from the top panel. 6 | 7 | ![Touchpad Indicator Screenshots](media/screenshots.gif) 8 | 9 | 10 | ## Installation 11 | 12 | **From GNOME Shell Extension Website** (recommended) 13 | 1. Visit [https://extensions.gnome.org/extension/131/touchpad-indicator/](https://extensions.gnome.org/extension/131/touchpad-indicator/) in Firefox browser. 14 | 2. Click on the switch at right side to toggle it from OFF to ON. 15 | 3. Accept any installation prompts. 16 | 17 | **From GitHub** 18 | 1. Open a terminal and run: 19 | ```bash 20 | rm -rf ~/.local/share/gnome-shell/extensions/touchpad-indicator@orangeshirt; 21 | git clone --depth=1 "https://github.com/askmrsinh/TouchpadIndicator.git" ~/.local/share/gnome-shell/extensions/touchpad-indicator@orangeshirt; 22 | ``` 23 | 2. Restart GNOME Shell by pressing `Alt+F2`, `r`, `Enter` or by Logging out and Logging in. 24 | 3. Enable the extension in *[gnome-tweak-tool](https://wiki.gnome.org/action/show/Apps/Tweaks)*. 25 | 26 | 27 | ## License 28 | 29 | Touchpad Indicator GNOME Shell Extension is distributed under the terms of the **[GNU General Public License, version 2 (GPL-2.0)](http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)**. 30 | -------------------------------------------------------------------------------- /Settings.ui: -------------------------------------------------------------------------------- 1 | 2 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | No events logged yet. 39 | 40 | 41 | 1 42 | 43 | 44 | 45 | 46 | 12 47 | 12 48 | 12 49 | 12 50 | vertical 51 | 24 52 | 53 | 54 | 55 | 56 | none 57 | 58 | 59 | 1 60 | 61 | 62 | 12 63 | 12 64 | 12 65 | 12 66 | 32 67 | 68 | 69 | 1 70 | Backend to use for enabling or disabling the Touchpad. 71 | 1 72 | 0 73 | 76 | 77 | 0 78 | 1 79 | 80 | 81 | 82 | 83 | 84 | 1 85 | Switch Method 86 | 0 87 | 88 | 0 89 | 0 90 | 91 | 92 | 93 | 94 | 95 | 6 96 | 97 | 98 | gsettings 99 | 100 | GSettings 101 | synclient 102 | xinput 103 | 104 | 105 | 106 | 107 | 1 108 | 0 109 | 2 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 1 120 | 121 | 122 | 12 123 | 12 124 | 12 125 | 12 126 | 32 127 | 128 | 129 | 6 130 | 131 | 132 | 1 133 | end 134 | center 135 | 1 136 | 137 | 138 | 139 | 1 140 | 0 141 | 2 142 | 143 | 144 | 145 | 146 | 147 | 1 148 | Show Icon 149 | 0 150 | 151 | 0 152 | 0 153 | 154 | 155 | 156 | 157 | 158 | 1 159 | If enabled, a persistent symbolic icon is shown in panel. 160 | 1 161 | 0 162 | 165 | 166 | 0 167 | 1 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 0 180 | 0 181 | Basic Settings 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | none 194 | 195 | 196 | 1 197 | 198 | 199 | 12 200 | 12 201 | 12 202 | 12 203 | 32 204 | 205 | 206 | 6 207 | 208 | 209 | 1 210 | end 211 | center 212 | 213 | 214 | 215 | 1 216 | 0 217 | 2 218 | 219 | 220 | 221 | 222 | 223 | 1 224 | Autoswitch Touchpad 225 | 0 226 | 227 | 0 228 | 0 229 | 230 | 231 | 232 | 233 | 234 | 1 235 | Toggle the touchpad when an external mouse is plugged/unplugged. 236 | 1 237 | 0 238 | 241 | 242 | 0 243 | 1 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 1 254 | 255 | 256 | 12 257 | 12 258 | 12 259 | 12 260 | 32 261 | 262 | 263 | 6 264 | 265 | 266 | 1 267 | end 268 | center 269 | 270 | 271 | 272 | 1 273 | 0 274 | 2 275 | 276 | 277 | 278 | 279 | 280 | 1 281 | Show Notifications 282 | 0 283 | 284 | 0 285 | 0 286 | 287 | 288 | 289 | 290 | 291 | 1 292 | Get notfications when touchpad is automatically toggled. 293 | 1 294 | 0 295 | 298 | 299 | 0 300 | 1 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 1 311 | 312 | 313 | start 314 | 12 315 | 12 316 | 12 317 | 12 318 | 32 319 | 320 | 321 | start 322 | 1 323 | Keybinding to force toggle the touchpad 324 | 325 | 0 326 | 0 327 | 328 | 329 | 330 | 331 | 332 | 1 333 | 1 334 | 335 | 1 336 | 0 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 0 349 | 0 350 | Auto Switch 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | none 363 | 364 | 365 | 1 366 | 367 | 368 | 12 369 | 12 370 | 12 371 | 12 372 | 32 373 | 374 | 375 | 1 376 | Use this to restore settings and enable all pointing devices. 377 | 1 378 | 0 379 | 382 | 383 | 0 384 | 1 385 | 386 | 387 | 388 | 389 | 390 | 1 391 | Reset Configuration 392 | 0 393 | 394 | 0 395 | 0 396 | 397 | 398 | 399 | 400 | 401 | 6 402 | 403 | 404 | Reset 405 | 1 406 | 1 407 | 410 | 411 | 412 | 413 | 1 414 | 0 415 | 2 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 1 435 | General 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 12 445 | 12 446 | 12 447 | 12 448 | vertical 449 | 24 450 | 451 | 452 | 453 | 454 | none 455 | 456 | 457 | 1 458 | 459 | 460 | 12 461 | 12 462 | 12 463 | 12 464 | 465 | 466 | 12 467 | Here you can find some details about your system which might be helpful in debugging. 468 | 1 469 | 1 470 | 0 471 | 472 | 0 473 | 0 474 | 2 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | start 483 | 6 484 | 2 485 | 18 486 | 1 487 | 488 | 489 | start 490 | - 491 | 1 492 | 493 | 1 494 | 0 495 | 496 | 497 | 498 | 499 | 500 | end 501 | 1 502 | Gnome Shell Version: 503 | 1 504 | 505 | 0 506 | 0 507 | 508 | 509 | 510 | 511 | 512 | end 513 | 1 514 | xinput: 515 | 1 516 | 517 | 0 518 | 7 519 | 520 | 521 | 522 | 523 | 524 | end 525 | 1 526 | synclient: 527 | 1 528 | 529 | 0 530 | 6 531 | 532 | 533 | 534 | 535 | 536 | org.gnome.desktop.peripherals.touchpad send-events 537 | end 538 | 1 539 | 'send-events' key: 540 | 1 541 | 542 | 0 543 | 5 544 | 545 | 546 | 547 | 548 | 549 | org.gnome.shell.extensions.touchpad-indicator trackpoint-enabled 550 | end 551 | 1 552 | 'touchpad-enabled' key: 553 | 1 554 | 555 | 0 556 | 4 557 | 558 | 559 | 560 | 561 | 562 | end 563 | 1 564 | Touchpad(s): 565 | 1 566 | 567 | 0 568 | 3 569 | 570 | 571 | 572 | 573 | 574 | end 575 | 1 576 | Switch Method: 577 | 1 578 | 579 | 0 580 | 2 581 | 582 | 583 | 584 | 585 | 586 | end 587 | 1 588 | Session Type: 589 | 1 590 | 591 | 0 592 | 1 593 | 594 | 595 | 596 | 597 | 598 | start 599 | - 600 | 1 601 | 602 | 1 603 | 7 604 | 605 | 606 | 607 | 608 | 609 | start 610 | - 611 | 1 612 | 613 | 1 614 | 6 615 | 616 | 617 | 618 | 619 | 620 | start 621 | - 622 | 1 623 | 624 | 1 625 | 5 626 | 627 | 628 | 629 | 630 | 631 | start 632 | - 633 | 1 634 | 635 | 1 636 | 4 637 | 638 | 639 | 640 | 641 | 642 | start 643 | - 644 | 1 645 | 1 646 | 647 | 1 648 | 3 649 | 650 | 651 | 652 | 653 | 654 | start 655 | - 656 | 1 657 | 658 | 1 659 | 2 660 | 661 | 662 | 663 | 664 | 665 | start 666 | - 667 | 1 668 | 669 | 1 670 | 1 671 | 672 | 673 | 674 | 675 | 676 | 677 | 0 678 | 1 679 | 2 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 0 692 | 0 693 | System Information 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | none 706 | 707 | 708 | 1 709 | 710 | 711 | 12 712 | 12 713 | 12 714 | 12 715 | 716 | 717 | 1 718 | 719 | 720 | 12 721 | 12 722 | 32 723 | 724 | 725 | 6 726 | 727 | 728 | 1 729 | end 730 | center 731 | 732 | 733 | 734 | 1 735 | 0 736 | 2 737 | 738 | 739 | 740 | 741 | 742 | 0 743 | Also write logs to a temporary file in extension folder 744 | 1 745 | 6 746 | 6 747 | 748 | 0 749 | 2 750 | 2 751 | 752 | 753 | 754 | 755 | 756 | 1 757 | Enable Debug logging 758 | 0 759 | 760 | 0 761 | 0 762 | 763 | 764 | 765 | 766 | 767 | 1 768 | Log extension events in <a href="https://wiki.archlinux.org/index.php/Systemd/Journal">systemd journal</a>. 769 | 1 770 | 1 771 | 0 772 | 775 | 776 | 0 777 | 1 778 | 779 | 780 | 781 | 782 | 783 | 784 | 0 785 | 0 786 | 2 787 | 788 | 789 | 790 | 791 | 792 | 0 793 | 150 794 | 1 795 | 12 796 | 1 797 | 798 | 799 | 0 800 | 1 801 | 0 802 | 0 803 | 1 804 | log_text_buffer 805 | 806 | 807 | 808 | 0 809 | 1 810 | 2 811 | 812 | 813 | 814 | 815 | 816 | start 817 | start 818 | dialog-information 819 | 820 | 0 821 | 2 822 | 823 | 824 | 825 | 826 | 827 | 8 828 | 1 829 | Please note that logging is resource intensive and can slow down performance. Keep logging disabled when not required. 830 | 1 831 | 1 832 | 0 833 | 834 | 1 835 | 2 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | Debug Logging 848 | 0 849 | 0 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 1 862 | Debug 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | vertical 872 | 873 | 874 | 12 875 | 12 876 | 12 877 | 12 878 | 879 | 880 | 12 881 | 12 882 | 12 883 | 12 884 | 885 | 886 | 12 887 | 0 888 | 0 889 | 890 | 891 | 12 892 | 12 893 | 894 | 895 | 6 896 | 6 897 | Automatically disable other pointing devices when an external mouse is plugged in. Optionally, switch the touchpad, trackpoint, fingertouch, touchscreen or a pen device on and off easily from the top panel. 898 | This a fork of orangeshirt's '<a href="https://github.com/orangeshirt/gnome-shell-extension-touchpad-indicator">gnome-shell-extension-touchpad-indicator</a>'. 899 | 1 900 | center 901 | 1 902 | 1 903 | 904 | 0 905 | 2 906 | 907 | 908 | 909 | 910 | 911 | 64 912 | input-touchpad 913 | 1 914 | 2 915 | 916 | 0 917 | 0 918 | 919 | 920 | 921 | 922 | 923 | 6 924 | 6 925 | Touchpad management GNOME Shell Extension 926 | center 927 | 1 928 | 1 929 | 930 | 931 | 932 | 933 | 0 934 | 1 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 100 945 | 80 946 | 1 947 | 0 948 | 0 949 | 950 | 951 | 12 952 | 12 953 | 12 954 | 12 955 | 6 956 | 32 957 | 958 | 959 | 1 960 | Please use <a href="https://github.com/user501254/TouchpadIndicator#touchpad-indicator">Github</a> for reporting bugs and feature requests. 961 | 1 962 | 1 963 | 0 964 | 967 | 968 | 0 969 | 1 970 | 971 | 972 | 973 | 974 | 975 | 1 976 | Feature Request / Bug Report 977 | 0 978 | 979 | 0 980 | 0 981 | 982 | 983 | 984 | 985 | 986 | 6 987 | 988 | 989 | New Issue 990 | 1 991 | 1 992 | 1 993 | 996 | 997 | 998 | 999 | 1 1000 | 0 1001 | 2 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | TouchpadIndicator-extensions.gnome.org-v 1014 | 1 1015 | 1 1016 | https://github.com/user501254/TouchpadIndicator/releases/ 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 12 1024 | 12 1025 | 1 1026 | 1027 | 1028 | end 1029 | 12 1030 | 12 1031 | 12 1032 | 12 1033 | 1034 | 1035 | 1 1036 | 0 1037 | 0 1038 | 1039 | 1040 | 1 1041 | end 1042 | <span size="small">This program comes with ABSOLUTELY NO WARRANTY. 1043 | See the <a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GNU General Public License, version 2 or later</a> for details.</span> 1044 | 1 1045 | center 1046 | 1 1047 | 1 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1 1064 | About 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | -------------------------------------------------------------------------------- /extension.js: -------------------------------------------------------------------------------- 1 | /* TouchpadIndicator - Touchpad management GNOME Shell Extension. 2 | * Orignal work Copyright (C) 2011-2013 Armin Köhler 3 | * Modifcations Copyright (C) 2019 Ashesh Singh 4 | * 5 | * This file is part of TouchpadIndicator, a fork of Armin Köhler's 6 | * 'gnome-shell-extension-touchpad-indicator' project which is licensed GPLv2. 7 | * Orignal source code is available at https://git.io/fjVec. 8 | * 9 | * This program is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation; either version 2 of the License, or (at your option) 12 | * any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 | * more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * this program; if not, write to: 21 | * The Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor 23 | * Boston, MA 02110-1301, USA. 24 | */ 25 | 26 | const { Gio, GLib, GObject, Meta, Shell, St } = imports.gi; 27 | const Mainloop = imports.mainloop; 28 | 29 | const Main = imports.ui.main; 30 | const PanelMenu = imports.ui.panelMenu; 31 | const PopupMenu = imports.ui.popupMenu; 32 | const MessageTray = imports.ui.messageTray; 33 | const ExtensionUtils = imports.misc.extensionUtils; 34 | 35 | const Me = ExtensionUtils.getCurrentExtension(); 36 | const Lib = Me.imports.lib; 37 | const XInput = Me.imports.xinput; 38 | const Synclient = Me.imports.synclient; 39 | 40 | //schema 41 | const SCHEMA_EXTENSION = 'org.gnome.shell.extensions.touchpad-indicator'; 42 | const SCHEMA_TOUCHPAD = 'org.gnome.desktop.peripherals.touchpad'; 43 | 44 | //keys 45 | const KEY_SEND_EVENTS = 'send-events'; 46 | const KEY_SWCH_METHOD = 'switchmethod'; 47 | const KEY_ALWAYS_SHOW = 'show-panelicon'; 48 | const KEY_NOTIFS_SHOW = 'show-notifications'; 49 | const KEY_TPD_ENABLED = 'touchpad-enabled'; 50 | const KEY_TPT_ENABLED = 'trackpoint-enabled'; 51 | const KEY_TSN_ENABLED = 'touchscreen-enabled'; 52 | const KEY_FTH_ENABLED = 'fingertouch-enabled'; 53 | const KEY_PEN_ENABLED = 'pen-enabled'; 54 | 55 | //icons 56 | const ICON_ENABLED = 'input-touchpad-symbolic'; 57 | 58 | //sets 59 | const NON_TPD_SET = [KEY_PEN_ENABLED, KEY_FTH_ENABLED, KEY_TSN_ENABLED, KEY_TPT_ENABLED]; 60 | 61 | //localization 62 | const Gettext = imports.gettext.domain(Me.metadata['gettext-domain']); 63 | const _ = Gettext.gettext; 64 | 65 | function logging(event) { 66 | if (Lib.DEBUG) { 67 | Lib.logger(`TouchpadIndicator.${event}`); 68 | } 69 | } 70 | 71 | var TouchpadIndicator = GObject.registerClass( 72 | class TouchpadIndicatorButton extends PanelMenu.Button { 73 | _init() { 74 | super._init(0.0, 'Touchpad Indicator'); 75 | this.hbox = new St.BoxLayout({ 76 | style_class: 'panel-status-menu-box' 77 | }); 78 | this.icon = new St.Icon({ 79 | icon_name: ICON_ENABLED, 80 | style_class: 'system-status-icon' 81 | }); 82 | this.hbox.add_child(this.icon); 83 | this.hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM)); 84 | this.add_child(this.hbox); 85 | 86 | this._extSettings = ExtensionUtils.getSettings(SCHEMA_EXTENSION); 87 | this._tpdSettings = new Gio.Settings({ schema_id: SCHEMA_TOUCHPAD }); 88 | 89 | // Purely for logging and debugging 90 | this._debug = this._extSettings.get_boolean('debug'); 91 | Lib.DEBUG = this._debug; 92 | this._keyDebugSignal = this._extSettings.connect( 93 | 'changed::debug', 94 | this._onDebugSignal.bind(this)); 95 | 96 | this._debugToFile = this._extSettings.get_boolean('debug-to-file'); 97 | Lib.DEBUG_TO_FILE = this._debugToFile; 98 | this._keyDebugToFileSignal = this._extSettings.connect( 99 | 'changed::debug-to-file', 100 | this._onDebugSignal.bind(this)); 101 | 102 | this._logEKeyChangeSignal = this._extSettings.connect( 103 | `changed::${KEY_TPD_ENABLED}`, 104 | this._logEKeyChange.bind(this)); 105 | this._logSKeyChangeSignal = this._tpdSettings.connect( 106 | `changed::${KEY_SEND_EVENTS}`, 107 | this._logSKeyChange.bind(this)); 108 | 109 | logging('_init()'); 110 | 111 | // Retrive all pointing device handlers 112 | this.pointingDevices = Lib.listPointingDevices()[1]; 113 | 114 | // Current session type 115 | // You may face issues using this extension under Wayland. 116 | // https://github.com/user501254/TouchpadIndicator/issues/11 117 | this._sessionType = Lib.SESSION_TYPE; 118 | logging(`_init(): Session type is ${this._sessionType}`); 119 | 120 | // TODO: Let user set program start touchpad state 121 | // None, Enabled, Disabled 122 | 123 | // Switch method to start with 124 | this._switchMethod = this._extSettings.get_enum(KEY_SWCH_METHOD); 125 | this._switchMethodChanged = false; 126 | 127 | logging(`_init(): Switch method is ${this._switchMethod}`); 128 | 129 | // SYNCLIENT related 130 | this.synclient = new Synclient.Synclient(); 131 | if (this.synclient.isUsable !== true && 132 | this._switchMethod === Lib.METHOD.SYNCLIENT) { 133 | logging('_init(): Can\'t use Synclient, defaulting to GSettings'); 134 | this._extSettings.set_enum(KEY_SWCH_METHOD, Lib.METHOD.GSETTINGS); 135 | this._switchMethodChanged = true; 136 | } 137 | 138 | // XINPUT related 139 | this.xinput = new XInput.XInput(); 140 | if (this.xinput.isUsable !== true && 141 | this._switchMethod === Lib.METHOD.XINPUT) { 142 | logging('_init(): Can\'t use Xinput, defaulting to GSettings'); 143 | this._extSettings.set_enum(KEY_SWCH_METHOD, Lib.METHOD.GSETTINGS); 144 | this._extSettings.set_boolean('autoswitch-trackpoint', false); 145 | this._switchMethodChanged = true; 146 | } 147 | 148 | // Resets 149 | if (this._switchMethod !== Lib.METHOD.SYNCLIENT) { 150 | this.synclient._enable(); 151 | } 152 | 153 | if (this._switchMethod !== Lib.METHOD.XINPUT) { 154 | this.xinput._enableByType("mouse"); 155 | } 156 | 157 | if (this._switchMethod !== Lib.METHOD.GSETTINGS) { 158 | if (this._tpdSettings.get_string(KEY_SEND_EVENTS) !== 'enabled' && 159 | this._extSettings.get_boolean(KEY_TPD_ENABLED) === true) 160 | this._tpdSettings.set_string(KEY_SEND_EVENTS, 'enabled'); 161 | } 162 | 163 | // System `send-events` change signal 164 | this._tpdSendEventsSignal = this._tpdSettings.connect( 165 | `changed::${KEY_SEND_EVENTS}`, 166 | this._queueSyncPointingDevice.bind(this)); 167 | 168 | // Extension `show-panelicon` change signal 169 | this._keyAlwaysShowSignal = this._extSettings.connect( 170 | `changed::${KEY_ALWAYS_SHOW}`, 171 | this._queueSyncMenuVisibility.bind(this)); 172 | 173 | // Extension `switchmethod` change signal 174 | this._keySwitchMthdSignal = this._extSettings.connect( 175 | `changed::${KEY_SWCH_METHOD}`, 176 | this._syncSwitchMethod.bind(this)); 177 | 178 | // Emulate that a mouse is currently plugged in 179 | this._onMouseDevicePlugged(2); 180 | 181 | this._queueSyncPointingDevice(KEY_TPD_ENABLED); 182 | this._updateIcon(); 183 | 184 | // To store all change signals on `*-enabled` extension keys 185 | this._enabledSignals = []; 186 | 187 | let touchpad = this._buildItem(_('Touchpad'), KEY_TPD_ENABLED); 188 | this.menu.addMenuItem(touchpad); 189 | 190 | if (this.xinput._isPresent('trackpoint')) { 191 | let trackpoint = this._buildItem(_('Trackpoint'), KEY_TPT_ENABLED); 192 | this.menu.addMenuItem(trackpoint); 193 | } 194 | if (this.xinput._isPresent('touchscreen')) { 195 | let touchscreen = this._buildItem(_('Touchscreen'), KEY_TSN_ENABLED); 196 | this.menu.addMenuItem(touchscreen); 197 | } 198 | if (this.xinput._isPresent('fingertouch')) { 199 | let fingertouch = this._buildItem(_('Fingertouch'), KEY_FTH_ENABLED); 200 | this.menu.addMenuItem(fingertouch); 201 | } 202 | if (this.xinput._isPresent('pen')) { 203 | let pen = this._buildItem(_('Pen'), KEY_PEN_ENABLED); 204 | this.menu.addMenuItem(pen); 205 | } 206 | 207 | this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); 208 | 209 | this.menu.addSettingsAction(_('Mouse & Touchpad Preferences'), 210 | 'gnome-mouse-panel.desktop'); 211 | this.menu.addAction(_('Indicator Preferences'), () => { 212 | Lib.executeCmdAsync(`gnome-extensions prefs ${Me.uuid}`); 213 | }); 214 | 215 | this._syncMenuVisibility(); 216 | 217 | this._watchDevInput = Lib.watchDevInput(); 218 | this._watchDevInputSignal = this._watchDevInput.connect('changed', 219 | this._onDevicePlugged.bind(this)); 220 | 221 | this._addKeybinding(); 222 | } 223 | 224 | _logSKeyChange() { 225 | logging('_logSKeyChange(): System `send-events` Key Changed'); 226 | } 227 | 228 | _logEKeyChange() { 229 | logging('_logEKeyChange(): Extension `touchpad-enabled` Key Changed'); 230 | } 231 | 232 | _buildItemExtended(string, initialValue, writable, onSet) { 233 | let widget = new PopupMenu.PopupSwitchMenuItem(string, 234 | initialValue); 235 | if (!writable) { 236 | widget.actor.reactive = false; 237 | } else { 238 | widget.connect('toggled', item => { 239 | onSet(item.state); 240 | }); 241 | } 242 | // TODO: Warn/Confirm if user is disabling the last pointing device. 243 | return widget; 244 | } 245 | 246 | _buildItem(string, key) { 247 | let signal = this._extSettings.connect(`changed::${key}`, () => { 248 | widget.setToggleState(this._extSettings.get_boolean(key)); 249 | this._queueSyncPointingDevice(key); 250 | this._queueSyncMenuVisibility(); 251 | this._updateIcon(); 252 | }); 253 | 254 | this._enabledSignals.push(signal); 255 | 256 | let widget = this._buildItemExtended(string, 257 | this._extSettings.get_boolean(key), 258 | this._extSettings.is_writable(key), 259 | (enabled) => { 260 | if (this._extSettings.get_boolean(key) !== enabled) { 261 | logging(`_buildItem(...): ${string} switch set to ${enabled}.`); 262 | this._extSettings.set_boolean(key, enabled); 263 | } 264 | }); 265 | return widget; 266 | } 267 | 268 | _queueSyncMenuVisibility() { 269 | if (this._syncMenuVisibilityIdle) { 270 | return; 271 | } 272 | 273 | this._syncMenuVisibilityIdle = Mainloop.idle_add( 274 | this._syncMenuVisibility.bind(this)); 275 | GLib.Source.set_name_by_id(this._syncMenuVisibilityIdle, 276 | '[gnome-shell] this._syncMenuVisibility'); 277 | } 278 | 279 | _syncMenuVisibility() { 280 | this._syncMenuVisibilityIdle = 0; 281 | 282 | let alwaysShow = this._extSettings.get_boolean(KEY_ALWAYS_SHOW); 283 | let items = this.menu._getMenuItems(); 284 | 285 | // Show panel icon if `show-panelicon` is true or at least one of the 286 | // device switches is in the off position. 287 | this.visible = alwaysShow || items.some(s => s.state === false); 288 | 289 | return GLib.SOURCE_REMOVE; 290 | } 291 | 292 | _notify(iconName, title, text) { 293 | if (this._notification) { 294 | this._notification.destroy(); 295 | } 296 | 297 | this._ensureSource(); 298 | 299 | let gicon = new Gio.ThemedIcon({ name: iconName }); 300 | this._notification = new MessageTray.Notification(this._source, title, 301 | text, { gicon: gicon }); 302 | this._notification.setUrgency(MessageTray.Urgency.LOW); 303 | this._notification.setTransient(true); 304 | this._notification.connect('destroy', () => { 305 | this._notification = null; 306 | }); 307 | this._source.showNotification(this._notification); 308 | } 309 | 310 | _ensureSource() { 311 | if (!this._source) { 312 | this._source = new MessageTray.Source('Touchpad Indicator', 313 | 'touchpad-indicator'); 314 | 315 | this._source.connect('destroy', () => { 316 | this._source = null; 317 | }); 318 | Main.messageTray.add(this._source); 319 | } 320 | } 321 | 322 | _syncSwitchMethod() { 323 | logging('_syncSwitchMethod()'); 324 | 325 | let oldSwitchMethod = this._switchMethod; 326 | 327 | this._switchMethod = this._extSettings.get_enum(KEY_SWCH_METHOD); 328 | this._switchMethodChanged = true; 329 | logging(`_syncSwitchMethod(): old ${oldSwitchMethod}`); 330 | logging(`_syncSwitchMethod(): new ${this._switchMethod}`); 331 | 332 | if (this._switchMethod !== Lib.METHOD.XINPUT) { 333 | this.xinput._enableByType('touchpad'); 334 | } 335 | if (this._switchMethod !== Lib.METHOD.SYNCLIENT) { 336 | this.synclient._enable(); 337 | } 338 | 339 | this._queueSyncPointingDevice(KEY_TPD_ENABLED); 340 | } 341 | 342 | _checkGconfSync(valTpdEnabled, valSendEvents) { 343 | logging(`_checkGconfSync(${valTpdEnabled}, ${valSendEvents})`); 344 | 345 | let bothEnabled = ((valTpdEnabled === true) && 346 | (valSendEvents === 'enabled')); 347 | let bothDisabled = ((valTpdEnabled === false) && 348 | (valSendEvents === 'disabled')); 349 | 350 | return (bothEnabled || bothDisabled); 351 | } 352 | 353 | _queueSyncPointingDevice(key) { 354 | logging(`_queueSyncPointingDevice(${key})`); 355 | 356 | // TODO: Check further for recursion, reduce complexity 357 | let valSendEvents = this._tpdSettings.get_string(KEY_SEND_EVENTS); 358 | let valTpdEnabled = this._extSettings.get_boolean(KEY_TPD_ENABLED); 359 | 360 | let isGconfInSync = this._checkGconfSync(valTpdEnabled, valSendEvents); 361 | 362 | // NOTE: When switch method is other than gconf (ie. xinput, synclient) 363 | // let system's touchpad settings (`send-events` key) work on top 364 | // of the switch method's touchpad enabling/disabling mechanism. 365 | if (isGconfInSync && (this._switchMethodChanged === false) && 366 | !NON_TPD_SET.includes(key)) { 367 | // TODO: Check this on gnome-shell reload. 368 | if (this._switchMethod !== Lib.METHOD.SYNCLIENT) { 369 | this.synclient._switch(valTpdEnabled); 370 | } 371 | logging('_queueSyncPointingDevice(...) - Already in sync.'); 372 | return; 373 | } 374 | 375 | switch (key) { 376 | case KEY_PEN_ENABLED: 377 | logging('_queueSyncPointingDevice(...): KEY_PEN_ENABLED'); 378 | this.xinput._switchByType( 379 | 'pen', this._extSettings.get_boolean(KEY_PEN_ENABLED)); 380 | break; 381 | case KEY_FTH_ENABLED: 382 | logging('_queueSyncPointingDevice(...): KEY_FTH_ENABLED'); 383 | this.xinput._switchByType( 384 | 'fingertouch', this._extSettings.get_boolean(KEY_FTH_ENABLED)); 385 | break; 386 | case KEY_TSN_ENABLED: 387 | logging('_queueSyncPointingDevice(...): KEY_TSN_ENABLED'); 388 | this.xinput._switchByType( 389 | 'touchscreen', this._extSettings.get_boolean(KEY_TSN_ENABLED)); 390 | break; 391 | case KEY_TPT_ENABLED: 392 | logging('_queueSyncPointingDevice(...): KEY_TPT_ENABLED'); 393 | this.xinput._switchByType( 394 | 'trackpoint', this._extSettings.get_boolean(KEY_TPT_ENABLED)); 395 | break; 396 | // Touchpad enabled/disabled through SCHEMA_EXTENSION `touchpad-enabled` 397 | case KEY_TPD_ENABLED: 398 | logging('_queueSyncPointingDevice(...): KEY_TPD_ENABLED'); 399 | this._syncTouchpad(valTpdEnabled, valSendEvents, isGconfInSync); 400 | break; 401 | // Touchpad enabled/disabled through SCHEMA_TOUCHPAD `send-events` 402 | default: 403 | logging('_queueSyncPointingDevice(...): default'); 404 | this._onsetSendEvents(valTpdEnabled, valSendEvents); 405 | } 406 | 407 | if (this._switchMethodChanged === true) { 408 | this._switchMethodChanged = false; 409 | } 410 | } 411 | 412 | _syncTouchpad(valTpdEnabled, valSendEvents, isGconfInSync) { 413 | logging(`_syncTouchpad(${valTpdEnabled}, ${valSendEvents}, ${isGconfInSync})`); 414 | 415 | // NOTE: When extension's `touchpad-enabled` key is changed, always 416 | // sync this change on to the system's `send-events` key, then 417 | // procceed to enable/disable touchpad through the current 418 | // switch method (if need be). 419 | switch (this._switchMethod) { 420 | case Lib.METHOD.GSETTINGS: 421 | logging('_syncTouchpad(...): Lib.METHOD.GSETTINGS'); 422 | this._onsetTouchpadEnable(valTpdEnabled, valSendEvents); 423 | break; 424 | case Lib.METHOD.XINPUT: 425 | logging('_syncTouchpad(...): Lib.METHOD.XINPUT'); 426 | if (isGconfInSync === false) { 427 | this._onsetTouchpadEnable(valTpdEnabled, valSendEvents); 428 | } 429 | this.xinput._switchByType('touchpad', valTpdEnabled); 430 | if ((valTpdEnabled === false) && 431 | !this.xinput._isPresent('touchpad')) { 432 | this._extSettings.set_boolean(KEY_TPD_ENABLED, true); 433 | } 434 | break; 435 | case Lib.METHOD.SYNCLIENT: 436 | logging('_syncTouchpad(...): Lib.METHOD.SYNCLIENT'); 437 | if (isGconfInSync === false) { 438 | this._onsetTouchpadEnable(valTpdEnabled, valSendEvents); 439 | } 440 | this.synclient._switch(valTpdEnabled); 441 | if ((valTpdEnabled === false) && 442 | !this.synclient.tpdOff) { 443 | this._extSettings.set_boolean(KEY_TPD_ENABLED, true); 444 | } 445 | break; 446 | } 447 | } 448 | 449 | _onsetSendEvents(valTpdEnabled, valSendEvents) { 450 | logging(`_onsetSendEvents(${valTpdEnabled}, ${valSendEvents})`); 451 | 452 | // `send-events` is OFF / not ON; `touchpad-enabled` is ON 453 | // set `touchpad-enabled` to OFF 454 | if ((valSendEvents !== 'enabled') && (valTpdEnabled !== false)) { 455 | logging('_onsetSendEvents(...): set `touchpad-enabled` to false'); 456 | this._extSettings.set_boolean(KEY_TPD_ENABLED, false); 457 | return; 458 | } 459 | // `send-events` is ON; `touchpad-enabled` is OFF 460 | // set `touchpad-enabled` to ON 461 | if ((valSendEvents === 'enabled') && (valTpdEnabled === false)) { 462 | // Reset if touchpad was externally enabled through gsettings 463 | // and extension switch method is other than gconf. 464 | if (this._switchMethod !== Lib.METHOD.GSETTINGS) { 465 | this.xinput._enableByType('touchpad'); 466 | this.synclient._enable(); 467 | } 468 | logging('_onsetSendEvents(...): set `touchpad-enabled` to true'); 469 | this._extSettings.set_boolean(KEY_TPD_ENABLED, true); 470 | } 471 | } 472 | 473 | _onsetTouchpadEnable(valTpdEnabled, valSendEvents) { 474 | logging(`_onsetTouchpadEnable(${valTpdEnabled}, ${valSendEvents})`); 475 | 476 | // `touchpad-enabled` is ON; `send-events` is OFF / not ON; 477 | // set `send-events` to ON 478 | if ((valTpdEnabled === true) && (valSendEvents !== 'enabled')) { 479 | logging('_onsetTouchpadEnable(...): set `send-events` to enabled'); 480 | this._tpdSettings.set_string(KEY_SEND_EVENTS, 'enabled'); 481 | return; 482 | } 483 | // `touchpad-enabled` is OFF; `send-events` is ON / not OFF; 484 | // set `send-events` to OFF 485 | if ((valTpdEnabled === false) && (valSendEvents !== 'disabled')) { 486 | logging('_onsetTouchpadEnable(...): set `send-events` to disabled'); 487 | this._tpdSettings.set_string(KEY_SEND_EVENTS, 'disabled'); 488 | } 489 | } 490 | 491 | _makeNotification(forType) { 492 | if (this._extSettings.get_boolean(KEY_NOTIFS_SHOW)) { 493 | let valSendEvents = this._tpdSettings.get_string(KEY_SEND_EVENTS); 494 | let valTpdEnabled = this._extSettings.get_boolean(KEY_TPD_ENABLED); 495 | 496 | if (valSendEvents === 'enabled' && valTpdEnabled) { 497 | this._notify('dialog-information', 498 | `${_('Touchpad Indicator')} ${Me.uuid}`, 499 | `${_(forType)} ${_('Enabled')}`); 500 | } else { 501 | this._notify('dialog-information', 502 | `${_('Touchpad Indicator')} ${Me.uuid}`, 503 | `${_(forType)} ${_('Disabled')}`); 504 | } 505 | } 506 | } 507 | 508 | _toggleTouchpadEnable() { 509 | this._extSettings.set_boolean( 510 | KEY_TPD_ENABLED, 511 | !this._extSettings.get_boolean(KEY_TPD_ENABLED)); 512 | } 513 | 514 | _addKeybinding() { 515 | // TODO: Simplify setup of custom keyboard shortcut. 516 | // issues/23#issuecomment-504754287, https://git.io/fjwX2 517 | let shortcut = this._extSettings.get_strv('toggle-touchpad'); 518 | this._extSettings.set_strv('toggle-touchpad', shortcut); 519 | Main.wm.addKeybinding('toggle-touchpad', this._extSettings, 520 | Meta.KeyBindingFlags.NONE, 521 | Shell.ActionMode.ALL, 522 | this._toggleTouchpadEnable.bind(this)); 523 | } 524 | 525 | _removeKeybinding() { 526 | Main.wm.removeKeybinding('toggle-touchpad'); 527 | } 528 | 529 | _updateIcon() { 530 | let valTpdEnabled = this._extSettings.get_boolean(KEY_TPD_ENABLED); 531 | this.icon.icon_name = valTpdEnabled ? 532 | ICON_ENABLED : 'touchpad-disabled-symbolic'; 533 | } 534 | 535 | _onDevicePlugged(filemonitor, file, otherFile, eventType) { 536 | logging(`_onDevicePlugged(...): ${file.get_path()} ${eventType}`); 537 | 538 | if (file.get_path().indexOf('mouse') !== -1) { 539 | if ((eventType > 1) && (eventType < 4)) { 540 | this._onMouseDevicePlugged(eventType); 541 | } 542 | } 543 | } 544 | 545 | _onMouseDevicePlugged(eventType) { 546 | logging(`_onMouseDevicePlugged(${eventType})`); 547 | 548 | // Retrive all pointing device handlers 549 | this.pointingDevices = Lib.listPointingDevices()[1]; 550 | 551 | // TODO: Check auto switch behaviour on resume from sleep, restart. 552 | // TODO: Consider autoswitch-* key was set to 'false' while touchpad 553 | // is disabled and then user unplugs the mouse. 554 | if (this._extSettings.get_boolean('autoswitch-touchpad')) { 555 | let mouseDevices = this.pointingDevices.filter(p => p.type === 'mouse'); 556 | let mouseCount = mouseDevices.length; 557 | logging(`_onMouseDevicePlugged(${eventType}) - mouseDevices are ${JSON.stringify(mouseDevices)}`); 558 | logging(`_onMouseDevicePlugged(${eventType}) - mouseCount is ${mouseCount}`); 559 | 560 | // no mouse device(s) is/are plugged in 561 | if (eventType === 2 && mouseCount === 0 && 562 | !this._extSettings.get_boolean(KEY_TPD_ENABLED)) { 563 | this._extSettings.set_boolean(KEY_TPD_ENABLED, true); 564 | this._makeNotification('Touchpad'); 565 | return; 566 | } 567 | // mouse device(s) is/are plugged in 568 | if (eventType === 3 && mouseCount !== 0 && 569 | this._extSettings.get_boolean(KEY_TPD_ENABLED)) { 570 | this._extSettings.set_boolean(KEY_TPD_ENABLED, false); 571 | this._makeNotification('Touchpad'); 572 | } 573 | } 574 | } 575 | 576 | _onDebugSignal() { 577 | this._debug = this._extSettings.get_boolean('debug'); 578 | Lib.DEBUG = this._debug; 579 | this._debugToFile = this._extSettings.get_boolean('debug-to-file'); 580 | Lib.DEBUG_TO_FILE = this._debugToFile; 581 | 582 | if (this._debug && this._debugToFile) { 583 | Lib.createLogFile(); 584 | } 585 | } 586 | 587 | _disconnectSignals() { 588 | this._watchDevInput.disconnect(this._watchDevInputSignal); 589 | this._watchDevInput.cancel(); 590 | for (let i = 0; i < this._enabledSignals.length; i++) { 591 | this._extSettings.disconnect(this._enabledSignals[i]); 592 | } 593 | this._extSettings.disconnect(this._keyDebugToFileSignal); 594 | this._extSettings.disconnect(this._keyDebugSignal); 595 | this._extSettings.disconnect(this._keySwitchMthdSignal); 596 | this._extSettings.disconnect(this._keyAlwaysShowSignal); 597 | this._tpdSettings.disconnect(this._tpdSendEventsSignal); 598 | 599 | this._extSettings.disconnect(this._logEKeyChangeSignal); 600 | this._tpdSettings.disconnect(this._logSKeyChangeSignal); 601 | } 602 | 603 | // Make sure to enable related config when extension is disabled 604 | _resetConfig() { 605 | logging('_resetConfig'); 606 | // TODO: Let user set program exit touchpad state 607 | // None, Enabled, Disabled 608 | this.synclient._enable(); 609 | this.xinput._enableAll(); 610 | 611 | this._tpdSettings.set_string(KEY_SEND_EVENTS, 'enabled'); 612 | } 613 | }); 614 | 615 | function init() { 616 | ExtensionUtils.initTranslations(); 617 | } 618 | 619 | let _indicator; 620 | 621 | function enable() { 622 | logging('enable()'); 623 | 624 | _indicator = new TouchpadIndicator; 625 | Main.panel.addToStatusArea('touchpad-indicator', _indicator); 626 | } 627 | 628 | function disable() { 629 | logging('disable()'); 630 | // NOTE: This is called when activating Lock Screen (eg. Super+L) besides 631 | // when explicitly disabling the extension eg. through Tweak Tool. 632 | _indicator._disconnectSignals(); 633 | _indicator._removeKeybinding(); 634 | _indicator._resetConfig(); 635 | _indicator.destroy(); 636 | } 637 | 638 | 639 | /* exported init enable disable*/ -------------------------------------------------------------------------------- /lib.js: -------------------------------------------------------------------------------- 1 | /* TouchpadIndicator - Touchpad management GNOME Shell Extension. 2 | * Orignal work Copyright (C) 2011-2013 Armin Köhler 3 | * Modifcations Copyright (C) 2019 Ashesh Singh 4 | * 5 | * This file is part of TouchpadIndicator, a fork of Armin Köhler's 6 | * 'gnome-shell-extension-touchpad-indicator' project which is licensed GPLv2. 7 | * Orignal source code is available at https://git.io/fjVec. 8 | * 9 | * This program is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation; either version 2 of the License, or (at your option) 12 | * any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 | * more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * this program; if not, write to: 21 | * The Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor 23 | * Boston, MA 02110-1301, USA. 24 | */ 25 | 26 | const { Gio, GLib } = imports.gi; 27 | const ByteArray = imports.byteArray; 28 | 29 | const Me = imports.misc.extensionUtils.getCurrentExtension(); 30 | 31 | // Debug Mode Settings 32 | const LOG_FILEPATH = GLib.build_filenamev([Me.path, 'touchpad-indicator.log']); 33 | const LOG_PREFIX = `[${Me.uuid}] `; 34 | var DEBUG = false; 35 | var DEBUG_TO_FILE = false; 36 | 37 | // Possible Devices 38 | const TOUCHPADS = ['touchpad', 'glidepoint', 'fingersensingpad', 'bcm5974', 'trackpad', 'smartpad']; 39 | const TRACKPOINTS = ['trackpoint', 'accu point', 'trackstick', 'touchstyk', 'pointing stick', 'dualpoint stick']; 40 | const TOUCHSCREENS = ['touchscreen', 'maxtouch', 'touch digitizer', 'touch system']; 41 | const FINGERTOUCHES = ['finger touch']; 42 | const PENS = ['pen stylus', 'pen eraser']; 43 | const OTHERS = []; 44 | var ALL_TYPES = { 45 | 'touchpad': TOUCHPADS, 46 | 'trackpoint': TRACKPOINTS, 47 | 'touchscreen': TOUCHSCREENS, 48 | 'fingertouch': FINGERTOUCHES, 49 | 'pen': PENS, 50 | 'other': OTHERS 51 | }; 52 | var ALL_TOUCHPADS = TOUCHPADS.slice(); 53 | var ALL_OTHERS = OTHERS.slice(); 54 | 55 | // Methods to enable or disable the touchpad 56 | var METHOD = { GSETTINGS: 0, SYNCLIENT: 1, XINPUT: 2 }; 57 | 58 | //Session Type 59 | var SESSION_TYPE = GLib.getenv('XDG_SESSION_TYPE'); 60 | 61 | function createLogFile(filepath) { 62 | const PERMISSIONS_MODE = 0o755; 63 | let isSuccess = false; 64 | filepath = (filepath !== undefined) ? filepath : LOG_FILEPATH; 65 | try { 66 | let file = Gio.File.new_for_path(filepath); 67 | let header = `${filepath}\n`; 68 | if (GLib.mkdir_with_parents(file.get_parent().get_path(), PERMISSIONS_MODE) === 0) { 69 | isSuccess = file.replace_contents(header, null, false, 70 | Gio.FileCreateFlags.REPLACE_DESTINATION, null)[0]; 71 | } 72 | return isSuccess; 73 | } catch (err) { 74 | let error = `Sorry could not create logfile!\n${err}`; 75 | return [isSuccess, error]; 76 | } 77 | 78 | } 79 | 80 | function writeLog(contents) { 81 | let isSuccess = false; 82 | try { 83 | let file = Gio.File.new_for_path(LOG_FILEPATH); 84 | let fileOutputStream = file.append_to(Gio.FileCreateFlags.NONE, null); 85 | isSuccess = fileOutputStream.write(contents, null).close(null); 86 | return isSuccess; 87 | } catch (err) { 88 | let error = `Sorry could not write to logfile!\n${err}`; 89 | return [isSuccess, error]; 90 | } 91 | } 92 | 93 | function readLog() { 94 | let [isSuccess, contents] = [false, '']; 95 | try { 96 | [isSuccess, contents] = GLib.file_get_contents(LOG_FILEPATH); 97 | return [isSuccess, ByteArray.toString(contents)]; 98 | } catch (err) { 99 | let error = `Sorry could not read from logfile!\n${err}`; 100 | return [isSuccess, error]; 101 | } 102 | } 103 | 104 | function logger(event) { 105 | // NOTE: Each file has preemptive check on DEBUG variable. 106 | // TODO: Structured logging. 107 | let timestamp = new Date(new Date().getTime()).toISOString(); 108 | let message = `${timestamp} ${event}`; 109 | 110 | if (typeof global !== 'undefined') { 111 | global.log(LOG_PREFIX + message); 112 | } else { 113 | log(LOG_PREFIX + message); 114 | } 115 | 116 | if (DEBUG_TO_FILE) { 117 | writeLog(`${message}\n`); 118 | } 119 | } 120 | 121 | function executeCmdAsync(command) { 122 | try { 123 | return GLib.spawn_command_line_async(command); 124 | } catch (err) { 125 | logger(err.message.toString()); 126 | return false; 127 | } 128 | } 129 | 130 | function executeCmdSync(command) { 131 | let [isSuccess, stdOut] = [false, '']; 132 | try { 133 | [isSuccess, stdOut] = GLib.spawn_command_line_sync(command); 134 | return [isSuccess, ByteArray.toString(stdOut).trim()]; 135 | } catch (err) { 136 | logger(err.message.toString()); 137 | return false; 138 | } 139 | } 140 | 141 | function watchLogFile(filepath) { 142 | filepath = (filepath !== undefined) ? filepath : LOG_FILEPATH; 143 | let file = Gio.File.new_for_path(filepath); 144 | return file.monitor_file(Gio.FileMonitorFlags.NONE, null); 145 | } 146 | 147 | function watchDevInput() { 148 | let file = Gio.file_new_for_path('/dev/input'); 149 | return file.monitor_directory(Gio.FileMonitorFlags.WATCH_MOUNTS, null); 150 | } 151 | 152 | function makePointingDevice(pointingDeviceLines) { 153 | //assuming that N: & P: always appear at lines 2 and 3 respectively 154 | if (pointingDeviceLines[1].startsWith('N: Name=') && 155 | pointingDeviceLines[2].startsWith('P: Phys=')) { 156 | let pointingDevice = {}; 157 | pointingDevice.name = pointingDeviceLines[1].split('"')[1]; 158 | pointingDevice.phys = pointingDeviceLines[2].split('=')[1]; 159 | pointingDevice.type = 'mouse'; //default 160 | for (let type in ALL_TYPES) { 161 | if (ALL_TYPES[type].some((t) => { 162 | return (pointingDevice.name.toLowerCase().indexOf(t) >= 0); 163 | })) { 164 | pointingDevice.type = type; 165 | break; 166 | } 167 | } 168 | logger(JSON.stringify(pointingDevice)); 169 | return pointingDevice; 170 | } 171 | } 172 | 173 | function listPointingDevices() { 174 | let pointingDevices = []; 175 | let comp = executeCmdSync('cat /proc/bus/input/devices'); 176 | let allDeviceChunks = comp[1].split('\n\n'); 177 | for (let x = 0; x < allDeviceChunks.length; x++) { 178 | if (allDeviceChunks[x].indexOf('mouse') !== -1) { 179 | let pointingDeviceLines = allDeviceChunks[x].split('\n'); 180 | let pointingDevice = makePointingDevice(pointingDeviceLines); 181 | if (pointingDevice !== undefined) { 182 | pointingDevices.push(pointingDevice); 183 | } 184 | } 185 | } 186 | if (pointingDevices[0]) { 187 | return [true, pointingDevices]; 188 | } else { 189 | return [false, ' - No Pointing Devices detected.\n']; 190 | } 191 | } 192 | 193 | function removeSource(...args) { 194 | return GLib.source_remove(...args); 195 | } 196 | 197 | function addTimeout(...args) { 198 | return GLib.timeout_add(GLib.PRIORITY_DEFAULT, ...args); 199 | } 200 | 201 | 202 | /* exported DEBUG METHOD createLogFile readLog executeCmdAsync listPointingDevices watchLogFile watchDevInput removeSource addTimeout */ -------------------------------------------------------------------------------- /lint/eslintrc-gjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true 4 | }, 5 | "extends": "eslint:recommended", 6 | "rules": { 7 | "array-bracket-newline": [ 8 | "error", 9 | "consistent" 10 | ], 11 | "array-bracket-spacing": [ 12 | "error", 13 | "never" 14 | ], 15 | "arrow-spacing": "error", 16 | "brace-style": "error", 17 | "comma-spacing": [ 18 | "error", 19 | { 20 | "before": false, 21 | "after": true 22 | } 23 | ], 24 | "indent": [ 25 | "error", 26 | 4, 27 | { 28 | "ignoredNodes": [ 29 | "CallExpression[callee.object.name=GObject][callee.property.name=registerClass] > ClassExpression:first-child" 30 | ], 31 | "MemberExpression": "off" 32 | } 33 | ], 34 | "key-spacing": [ 35 | "error", 36 | { 37 | "beforeColon": false, 38 | "afterColon": true 39 | } 40 | ], 41 | "keyword-spacing": [ 42 | "error", 43 | { 44 | "before": true, 45 | "after": true 46 | } 47 | ], 48 | "linebreak-style": [ 49 | "error", 50 | "unix" 51 | ], 52 | "no-empty": [ 53 | "error", 54 | { 55 | "allowEmptyCatch": true 56 | } 57 | ], 58 | "no-implicit-coercion": [ 59 | "error", 60 | { 61 | "allow": ["!!"] 62 | } 63 | ], 64 | "no-restricted-properties": [ 65 | "error", 66 | { 67 | "object": "Lang", 68 | "property": "bind", 69 | "message": "Use arrow notation or Function.prototype.bind()" 70 | }, 71 | { 72 | "object": "Lang", 73 | "property": "Class", 74 | "message": "Use ES6 classes" 75 | } 76 | ], 77 | "nonblock-statement-body-position": [ 78 | "error", 79 | "below" 80 | ], 81 | "object-curly-newline": [ 82 | "error", 83 | { 84 | "consistent": true 85 | } 86 | ], 87 | "object-curly-spacing": "error", 88 | "prefer-template": "error", 89 | "quotes": [ 90 | "error", 91 | "single", 92 | { 93 | "avoidEscape": true 94 | } 95 | ], 96 | "semi": [ 97 | "error", 98 | "always" 99 | ], 100 | "semi-spacing": [ 101 | "error", 102 | { 103 | "before": false, 104 | "after": true 105 | } 106 | ], 107 | "space-before-blocks": "error", 108 | "space-infix-ops": [ 109 | "error", 110 | { 111 | "int32Hint": false 112 | } 113 | ] 114 | }, 115 | "globals": { 116 | "ARGV": false, 117 | "Debugger": false, 118 | "GIRepositoryGType": false, 119 | "imports": false, 120 | "Intl": false, 121 | "log": false, 122 | "logError": false, 123 | "print": false, 124 | "printerr": false, 125 | "window": false 126 | }, 127 | "parserOptions": { 128 | "ecmaVersion": 2017 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /lint/eslintrc-legacy.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [ 4 | "error", 5 | 4, 6 | { 7 | "ignoredNodes": [ 8 | "CallExpression > ArrowFunctionExpression", 9 | "CallExpression[callee.object.name=GObject][callee.property.name=registerClass] > ClassExpression:first-child" 10 | ], 11 | "CallExpression": { "arguments": "first" }, 12 | "MemberExpression": "off" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lint/eslintrc-shell.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "camelcase": [ 4 | "error", 5 | { 6 | "properties": "never", 7 | "allow": ["^vfunc_"] 8 | } 9 | ], 10 | "no-unused-vars": [ 11 | "error", 12 | { 13 | "argsIgnorePattern": "^_", 14 | "varsIgnorePattern": "_$" 15 | } 16 | ], 17 | "object-curly-spacing": [ 18 | "error", 19 | "always" 20 | ], 21 | "prefer-arrow-callback": "error" 22 | }, 23 | "globals": { 24 | "global": false, 25 | "_": false, 26 | "C_": false, 27 | "N_": false, 28 | "ngettext": false 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lint/generate-report.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | SEP=`printf '\t'` 3 | OUTPUT=/dev/stderr 4 | CWD=`pwd` 5 | SRCDIR=`dirname $0` 6 | 7 | run_lint() { 8 | eslint -f unix "$@" . 9 | } 10 | 11 | parse_opts() { 12 | tmp=`getopt -l output: o: "$@"` 13 | [ $? -ne 0 ] && exit 1 14 | 15 | eval set -- $tmp 16 | while true 17 | do 18 | case $1 in 19 | --output|-o) 20 | OUTPUT=`realpath $2`; shift 2; continue ;; 21 | --) 22 | shift; break ;; 23 | esac 24 | done 25 | } 26 | 27 | # delete lines that don't start with '/', 28 | # replace the first space with tab, sort 29 | process_for_join() { 30 | sed -E "/\//!d; s|(\S+)\s|\1$SEP|" | sort -k 1b,1 31 | } 32 | 33 | # re-replace tab with space 34 | process_post_join() { 35 | sed -E "s|$SEP| |" 36 | } 37 | 38 | create_report() { 39 | tmp1=`mktemp --tmpdir lint-XXXX` 40 | run_lint | process_for_join > $tmp1 41 | 42 | tmp2=`mktemp --tmpdir lint-XXXX` 43 | run_lint -c lint/eslintrc-legacy.json | process_for_join > $tmp2 44 | 45 | join -t"$SEP" -o '0,1.2' $tmp1 $tmp2 | process_post_join 46 | rm $tmp1 $tmp2 47 | } 48 | 49 | 50 | parse_opts "$@" 51 | 52 | cd $SRCDIR/.. 53 | 54 | create_report | tee $OUTPUT | grep -q . 55 | rv=$(( $? == 0 )) 56 | 57 | cd $CWD 58 | 59 | [ $rv -eq 0 -a -f $OUTPUT ] && rm $OUTPUT 60 | 61 | exit $rv 62 | -------------------------------------------------------------------------------- /locale/hi/LC_MESSAGES/touchpad-indicator.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askmrsinh/touchpad-indicator/4af2301297e7225989c9ff7ae4cef3a6cbd47616/locale/hi/LC_MESSAGES/touchpad-indicator.mo -------------------------------------------------------------------------------- /locale/hi/LC_MESSAGES/touchpad-indicator.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the Touchpad Indicator package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: Touchpad Indicator\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2019-11-07 21:10-0600\n" 11 | "PO-Revision-Date: 2019-11-07 21:10-0600\n" 12 | "Last-Translator: \n" 13 | "Language-Team: \n" 14 | "Language: hi\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "X-Generator: Poedit 2.2.4\n" 19 | "Plural-Forms: nplurals=2; plural=(n==0 || n==1);\n" 20 | "X-Poedit-SourceCharset: UTF-8\n" 21 | "X-Poedit-Basepath: ../../..\n" 22 | "X-Poedit-SearchPath-0: extension.js\n" 23 | "X-Poedit-SearchPath-1: prefs.js\n" 24 | "X-Poedit-SearchPath-2: Settings.ui\n" 25 | 26 | #: Settings.ui:37 27 | msgid "No events logged yet." 28 | msgstr "कोई घटना अभी तक लॉग नहीं हुई है।" 29 | 30 | #: Settings.ui:81 31 | msgid "Backend to use for enabling or disbaling the Touchpad." 32 | msgstr "टचपैड को सक्षम या अक्षम करने के लिए उपयोग करने के लिए बैकेंड।" 33 | 34 | #: Settings.ui:98 35 | msgid "Switch Method" 36 | msgstr "स्विच विधि" 37 | 38 | #: Settings.ui:182 39 | msgid "Show Icon" 40 | msgstr "आइकॉन दिखाओ" 41 | 42 | #: Settings.ui:195 43 | msgid "If enabled, a persistent symbolic icon is shown in panel." 44 | msgstr "यदि सक्षम है, तो नित्य प्रतीकात्मक आइकन पैनल में दिखाई देगा।" 45 | 46 | #: Settings.ui:225 47 | msgid "Basic Settings" 48 | msgstr "मूल सेटिंग्स" 49 | 50 | #: Settings.ui:294 51 | msgid "Autoswitch Touchpad" 52 | msgstr "ऑटोस्विच टचपैड" 53 | 54 | #: Settings.ui:307 55 | msgid "Toggle the touchpad when an external mouse is plugged/unplugged." 56 | msgstr "टचपैड को तब टॉगल करें जब बाहरी माउस प्लग / अनप्लग हो।" 57 | 58 | #: Settings.ui:366 59 | msgid "Show Notifications" 60 | msgstr "सूचनाएं दिखाएं" 61 | 62 | #: Settings.ui:379 63 | msgid "Get notfications when touchpad is automatically toggled." 64 | msgstr "जब टचपैड स्वचालित रूप से टॉगल किया जाता है तो नोटिफिकेशन प्राप्त करें।" 65 | 66 | #: Settings.ui:415 67 | msgid "Kebinding to force toggle the touchpad" 68 | msgstr "टचपैड को टॉगल करने के लिए कीबोर्ड शॉर्टकट" 69 | 70 | #: Settings.ui:452 71 | msgid "Auto Switch" 72 | msgstr "स्वचालित स्विच" 73 | 74 | #: Settings.ui:496 75 | msgid "Use this to restore settings and enable all pointing devices." 76 | msgstr "सेटिंग्स को पुनर्स्थापित करने और सभी पॉइंटिंग डिवाइस को सक्षम करने के लिए इसका उपयोग करें।" 77 | 78 | #: Settings.ui:513 79 | msgid "Reset Configuration" 80 | msgstr "कॉन्फ़िगरेशन रीसेट करें" 81 | 82 | #: Settings.ui:528 83 | msgid "Reset" 84 | msgstr "रीसेट" 85 | 86 | #: Settings.ui:574 87 | msgid "General" 88 | msgstr "आम" 89 | 90 | #: Settings.ui:618 91 | msgid "Here you can find some details about your system which might be helpful in debugging." 92 | msgstr "यहां आप अपने सिस्टम के बारे में कुछ विवरण पा सकते हैं जो डिबगिंग में सहायक हो सकता है।" 93 | 94 | #: Settings.ui:861 95 | msgid "System Information" 96 | msgstr "प्रणाली की जानकारी" 97 | 98 | #: Settings.ui:937 99 | msgid "Also write logs to a temporary file in extension folder" 100 | msgstr "एक्सटेंशन फ़ोल्डर में एक अस्थायी फ़ाइल में लॉग भी लिखें" 101 | 102 | #: Settings.ui:955 103 | msgid "Enable Debug logging" 104 | msgstr "दोषमार्जन प्रचालेखन सुरु करे" 105 | 106 | #: Settings.ui:968 107 | msgid "" 108 | "Log extension events in systemd journal." 110 | msgstr "" 111 | "systemd journal में " 112 | "एक्सटेंशन ईवेंट लॉग करें।" 113 | 114 | #: Settings.ui:1032 115 | msgid "" 116 | "Please note that logging is resource intensive and can slow down performance. Keep logging " 117 | "disabled when not required." 118 | msgstr "" 119 | "कृपया ध्यान दें कि लॉगिंग संसाधन गहन है और प्रदर्शन को धीमा कर सकता है। आवश्यकता न होने पर लॉगिंग को अक्षम " 120 | "रखें।" 121 | 122 | #: Settings.ui:1060 123 | msgid "Debug Logging" 124 | msgstr "दोषमार्जन प्रचालेखन" 125 | 126 | #: Settings.ui:1085 127 | msgid "Debug" 128 | msgstr "दोषमार्जन" 129 | 130 | #: Settings.ui:1134 131 | msgid "" 132 | "Automatically disable other pointing devices when an external mouse is plugged in. " 133 | "Optionally, switch the touchpad, trackpoint, fingertouch, touchscreen or a pen device on and " 134 | "off easily from the top panel.\n" 135 | "\n" 136 | "This a fork of orangeshirt's 'gnome-shell-extension-touchpad-indicator'." 138 | msgstr "" 139 | "बाहरी माउस को प्लग इन करने पर अन्य पॉइंटिंग डिवाइस को स्वचालित रूप से अक्षम करें। वैकल्पिक रूप से, टचपैड, " 140 | "ट्रैकपॉइंट, फिंगरप्रिंट, टचस्क्रीन या एक पेन डिवाइस को स्विच करें और शीर्ष पैनल से आसानी से बंद करें।\n" 141 | "\n" 142 | "यह orangeshirt के ' gnome-shell-extension-touchpad-indicator का एक फोर्क है।" 144 | 145 | #: Settings.ui:1167 146 | msgid "Touchpad management GNOME Shell Extension" 147 | msgstr "टचपैड प्रबंधन गनोम शैल एक्सटेंशन" 148 | 149 | #: Settings.ui:1207 150 | msgid "" 151 | "Please use Github for reporting bugs and feature requests." 153 | msgstr "" 154 | "बग्स और फ़ीचर अनुरोधों की रिपोर्टिंग के लिए कृपया Github का उपयोग करें।" 156 | 157 | #: Settings.ui:1225 158 | msgid "Feature Request / Bug Report" 159 | msgstr "फ़ीचर अनुरोध / बग रिपोर्ट" 160 | 161 | #: Settings.ui:1240 162 | msgid "New Issue" 163 | msgstr "नया मुद्दा" 164 | 165 | #: Settings.ui:1355 166 | msgid "About" 167 | msgstr "विवरण" 168 | 169 | #: extension.js:488 extension.js:492 170 | msgid "Touchpad Indicator" 171 | msgstr "टचपैड संकेतक" 172 | 173 | #: extension.js:489 174 | msgid "Enabled" 175 | msgstr "सक्षम है" 176 | 177 | #: extension.js:493 178 | msgid "Disabled" 179 | msgstr "अक्षम है" 180 | 181 | #~ msgid "Touchpad" 182 | #~ msgstr "टचपैड" 183 | 184 | #~ msgid "Trackpoint" 185 | #~ msgstr "ट्रैकपॉइंट" 186 | 187 | #~ msgid "Touchscreen" 188 | #~ msgstr "टचस्क्रीन" 189 | 190 | #~ msgid "Fingertouch" 191 | #~ msgstr "फिंगरटच" 192 | 193 | #~ msgid "Pen" 194 | #~ msgstr "पेन" 195 | 196 | #~ msgid "Mouse & Touchpad Preferences" 197 | #~ msgstr "माउस व टचपैड की पूर्ववृत्ति" 198 | 199 | #~ msgid "Indicator Preferences" 200 | #~ msgstr "संकेतक की पूर्ववृत्ति" 201 | 202 | #~ msgid "" 203 | #~ "These details are a snapshot of the system prior to opening this preference " 204 | #~ "window. Any setting changes made in current window session will not refelct above but " 205 | #~ "will be applied." 206 | #~ msgstr "" 207 | #~ "ये विवरण इस वरीयता विंडो को खोलने से पहले सिस्टम का एक स्नैपशॉट हैं। वर्तमान विंडो सत्र में किए " 208 | #~ "गए कोई भी सेटिंग परिवर्तन ऊपर से रिफलेक्ट नहीं होंगे पर लागू किए जाएंगे।" 209 | -------------------------------------------------------------------------------- /locale/touchpad-indicator.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the Touchpad Indicator package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Touchpad Indicator\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2019-11-07 21:05-0600\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "X-Generator: Poedit 2.2.4\n" 19 | "X-Poedit-Basepath: ..\n" 20 | "X-Poedit-SearchPath-0: Settings.ui\n" 21 | "X-Poedit-SearchPath-1: prefs.js\n" 22 | "X-Poedit-SearchPath-2: extension.js\n" 23 | 24 | #: Settings.ui:37 25 | msgid "No events logged yet." 26 | msgstr "" 27 | 28 | #: Settings.ui:81 29 | msgid "Backend to use for enabling or disbaling the Touchpad." 30 | msgstr "" 31 | 32 | #: Settings.ui:98 33 | msgid "Switch Method" 34 | msgstr "" 35 | 36 | #: Settings.ui:182 37 | msgid "Show Icon" 38 | msgstr "" 39 | 40 | #: Settings.ui:195 41 | msgid "If enabled, a persistent symbolic icon is shown in panel." 42 | msgstr "" 43 | 44 | #: Settings.ui:225 45 | msgid "Basic Settings" 46 | msgstr "" 47 | 48 | #: Settings.ui:294 49 | msgid "Autoswitch Touchpad" 50 | msgstr "" 51 | 52 | #: Settings.ui:307 53 | msgid "Toggle the touchpad when an external mouse is plugged/unplugged." 54 | msgstr "" 55 | 56 | #: Settings.ui:366 57 | msgid "Show Notifications" 58 | msgstr "" 59 | 60 | #: Settings.ui:379 61 | msgid "Get notfications when touchpad is automatically toggled." 62 | msgstr "" 63 | 64 | #: Settings.ui:415 65 | msgid "Kebinding to force toggle the touchpad" 66 | msgstr "" 67 | 68 | #: Settings.ui:452 69 | msgid "Auto Switch" 70 | msgstr "" 71 | 72 | #: Settings.ui:496 73 | msgid "Use this to restore settings and enable all pointing devices." 74 | msgstr "" 75 | 76 | #: Settings.ui:513 77 | msgid "Reset Configuration" 78 | msgstr "" 79 | 80 | #: Settings.ui:528 81 | msgid "Reset" 82 | msgstr "" 83 | 84 | #: Settings.ui:574 85 | msgid "General" 86 | msgstr "" 87 | 88 | #: Settings.ui:618 89 | msgid "Here you can find some details about your system which might be helpful in debugging." 90 | msgstr "" 91 | 92 | #: Settings.ui:861 93 | msgid "System Information" 94 | msgstr "" 95 | 96 | #: Settings.ui:937 97 | msgid "Also write logs to a temporary file in extension folder" 98 | msgstr "" 99 | 100 | #: Settings.ui:955 101 | msgid "Enable Debug logging" 102 | msgstr "" 103 | 104 | #: Settings.ui:968 105 | msgid "Log extension events in systemd journal." 106 | msgstr "" 107 | 108 | #: Settings.ui:1032 109 | msgid "Please note that logging is resource intensive and can slow down performance. Keep logging disabled when not required." 110 | msgstr "" 111 | 112 | #: Settings.ui:1060 113 | msgid "Debug Logging" 114 | msgstr "" 115 | 116 | #: Settings.ui:1085 117 | msgid "Debug" 118 | msgstr "" 119 | 120 | #: Settings.ui:1134 121 | msgid "" 122 | "Automatically disable other pointing devices when an external mouse is plugged in. Optionally, switch the touchpad, trackpoint, fingertouch, touchscreen or a pen device on and off easily from the top panel.\n" 123 | "\n" 124 | "This a fork of orangeshirt's 'gnome-shell-extension-touchpad-indicator'." 125 | msgstr "" 126 | 127 | #: Settings.ui:1167 128 | msgid "Touchpad management GNOME Shell Extension" 129 | msgstr "" 130 | 131 | #: Settings.ui:1207 132 | msgid "Please use Github for reporting bugs and feature requests." 133 | msgstr "" 134 | 135 | #: Settings.ui:1225 136 | msgid "Feature Request / Bug Report" 137 | msgstr "" 138 | 139 | #: Settings.ui:1240 140 | msgid "New Issue" 141 | msgstr "" 142 | 143 | #: Settings.ui:1355 144 | msgid "About" 145 | msgstr "" 146 | 147 | #: extension.js:488 extension.js:492 148 | msgid "Touchpad Indicator" 149 | msgstr "" 150 | 151 | #: extension.js:489 152 | msgid "Enabled" 153 | msgstr "" 154 | 155 | #: extension.js:493 156 | msgid "Disabled" 157 | msgstr "" 158 | -------------------------------------------------------------------------------- /media/Screenshot from 2019-07-01 14-41-27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askmrsinh/touchpad-indicator/4af2301297e7225989c9ff7ae4cef3a6cbd47616/media/Screenshot from 2019-07-01 14-41-27.png -------------------------------------------------------------------------------- /media/Screenshot from 2019-07-01 14-52-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askmrsinh/touchpad-indicator/4af2301297e7225989c9ff7ae4cef3a6cbd47616/media/Screenshot from 2019-07-01 14-52-06.png -------------------------------------------------------------------------------- /media/Screenshot from 2019-07-01 14-52-23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askmrsinh/touchpad-indicator/4af2301297e7225989c9ff7ae4cef3a6cbd47616/media/Screenshot from 2019-07-01 14-52-23.png -------------------------------------------------------------------------------- /media/Screenshot from 2019-07-01 15-30-35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askmrsinh/touchpad-indicator/4af2301297e7225989c9ff7ae4cef3a6cbd47616/media/Screenshot from 2019-07-01 15-30-35.png -------------------------------------------------------------------------------- /media/screenshots.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askmrsinh/touchpad-indicator/4af2301297e7225989c9ff7ae4cef3a6cbd47616/media/screenshots.gif -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Touchpad Indicator", 3 | "description": "Automatically disable other pointing devices when an external mouse is plugged in.", 4 | "uuid": "touchpad-indicator@orangeshirt", 5 | "shell-version": [ 6 | "3.38", 7 | "40" 8 | ], 9 | "gettext-domain": "touchpad-indicator", 10 | "url": "https://github.com/user501254/TouchpadIndicator#touchpadindicator", 11 | "repository": "https://github.com/user501254/TouchpadIndicator" 12 | } 13 | -------------------------------------------------------------------------------- /prefs.js: -------------------------------------------------------------------------------- 1 | /* TouchpadIndicator - Touchpad management GNOME Shell Extension. 2 | * Orignal work Copyright (C) 2011-2013 Armin Köhler 3 | * Modifcations Copyright (C) 2019 Ashesh Singh 4 | * 5 | * This file is part of TouchpadIndicator, a fork of Armin Köhler's 6 | * 'gnome-shell-extension-touchpad-indicator' project which is licensed GPLv2. 7 | * Orignal source code is available at https://git.io/fjVec. 8 | * 9 | * This program is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation; either version 2 of the License, or (at your option) 12 | * any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 | * more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * this program; if not, write to: 21 | * The Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor 23 | * Boston, MA 02110-1301, USA. 24 | */ 25 | 26 | const { Gio, Gtk } = imports.gi; 27 | 28 | const ExtensionUtils = imports.misc.extensionUtils; 29 | 30 | const Me = ExtensionUtils.getCurrentExtension(); 31 | const Lib = Me.imports.lib; 32 | const XInput = Me.imports.xinput; 33 | const Synclient = Me.imports.synclient; 34 | 35 | // Settings 36 | const SCHEMA_EXTENSION = 'org.gnome.shell.extensions.touchpad-indicator'; 37 | const SCHEMA_TOUCHPAD = 'org.gnome.desktop.peripherals.touchpad'; 38 | 39 | var Settings = class TouchpadIndicatorSettings { 40 | constructor() { 41 | 42 | let settings = new Gio.Settings({ schema_id: SCHEMA_TOUCHPAD }); 43 | let synclient = new Synclient.Synclient(); 44 | let xinput = new XInput.XInput(); 45 | 46 | this._settings = ExtensionUtils.getSettings(SCHEMA_EXTENSION); 47 | 48 | this._rtl = (Gtk.Widget.get_default_direction() === Gtk.TextDirection.RTL); 49 | 50 | this._builder = new Gtk.Builder(); 51 | this._builder.set_translation_domain(Me.metadata['gettext-domain']); 52 | this._builder.add_from_file(`${Me.path}/Settings.ui`); 53 | 54 | this.widget = new Gtk.ScrolledWindow({ 55 | hscrollbar_policy: Gtk.PolicyType.NEVER 56 | }); 57 | this._notebook = this._builder.get_object('ti_notebook'); 58 | this.widget.set_child(this._notebook); 59 | 60 | this._populateGeneralTab(synclient, xinput); 61 | this._populateDebugTab(settings, synclient, xinput); 62 | this._populateAboutTab(); 63 | 64 | this._bindSettings(settings, synclient, xinput); 65 | 66 | // Set a reasonable minimal window height 67 | this.widget.set_size_request(640, 720); 68 | } 69 | 70 | _bindSettings(settings, synclient, xinput) { 71 | // repopulate debug tab on notebook page switch 72 | this._builder.get_object('ti_notebook').connect('switch-page', 73 | () => { 74 | this._populateDebugTab(settings, synclient, xinput); 75 | }); 76 | 77 | // on General tab 78 | this._settings.bind('switchmethod', 79 | this._builder.get_object('switchmethod_combo'), 80 | 'active-id', 81 | Gio.SettingsBindFlags.DEFAULT); 82 | 83 | this._settings.bind('show-panelicon', 84 | this._builder.get_object('show_panelicon_switch'), 85 | 'active', 86 | Gio.SettingsBindFlags.DEFAULT); 87 | 88 | this._settings.bind('autoswitch-touchpad', 89 | this._builder.get_object('autoswitch_touchpad_switch'), 90 | 'active', 91 | Gio.SettingsBindFlags.DEFAULT); 92 | 93 | this._settings.bind('show-notifications', 94 | this._builder.get_object('show_notifications_switch'), 95 | 'active', 96 | Gio.SettingsBindFlags.DEFAULT); 97 | 98 | this._builder.get_object('reset_button').connect('clicked', 99 | () => { 100 | let keys = this._settings.list_keys(); 101 | for (let i = 0; i < keys.length; i++) { 102 | this._settings.reset(keys[i]); 103 | } 104 | 105 | synclient._enable(); 106 | xinput._enableAll(); 107 | 108 | this._builder.get_object('reset_button').set_sensitive(false); 109 | }); 110 | 111 | // on Debug tab 112 | this._settings.bind('debug', 113 | this._builder.get_object('debug_switch'), 114 | 'active', 115 | Gio.SettingsBindFlags.DEFAULT); 116 | 117 | this._settings.bind('debug-to-file', 118 | this._builder.get_object('debug_to_file_checkbox'), 119 | 'active', 120 | Gio.SettingsBindFlags.DEFAULT); 121 | 122 | this._builder.get_object('debug_switch').connect('state-set', 123 | () => { 124 | let state = !this._builder.get_object('debug_switch').get_state(); 125 | this._builder.get_object('debug_to_file_checkbox').set_visible(state); 126 | this._builder.get_object('debug_to_file_checkbox').set_active(state); 127 | }); 128 | 129 | this._builder.get_object('debug_to_file_checkbox').connect('toggled', 130 | () => { 131 | let state = this._builder.get_object('debug_to_file_checkbox').get_active(); 132 | this._builder.get_object('log_scrolled_window').set_visible(state); 133 | this._builder.get_object('log_text_view').set_visible(state); 134 | }); 135 | 136 | this._watchLogFile = Lib.watchLogFile(); 137 | this._watchLogFileSignal = this._watchLogFile.connect('changed', 138 | this._updateLogView.bind(this)); 139 | 140 | // on About tab 141 | this._builder.get_object('issue_button').connect('clicked', 142 | () => { 143 | Lib.executeCmdAsync(`xdg-open ${Me.metadata.repository}/issues/new/choose`); 144 | }); 145 | } 146 | 147 | _populateGeneralTab(synclient, xinput) { 148 | if (xinput.isUsable !== true) { 149 | this._builder.get_object('switchmethod_combo').remove( 150 | Lib.METHOD.XINPUT 151 | ); 152 | } 153 | 154 | if (synclient.isUsable !== true) { 155 | this._builder.get_object('switchmethod_combo').remove( 156 | Lib.METHOD.SYNCLIENT 157 | ); 158 | } 159 | 160 | // Format the toggle Touchpad shortcut string. 161 | // Setting incorrect custom keybinding is user's fault. 162 | let toggleTouchpad = this._settings.get_strv('toggle-touchpad').toString(); 163 | toggleTouchpad = toggleTouchpad.split(/<(.*?)>/g).filter(Boolean).join(' + '); 164 | toggleTouchpad = `${toggleTouchpad}`; 165 | this._builder.get_object('toggle_touchpad_label').set_label(toggleTouchpad); 166 | } 167 | 168 | _populateDebugTab(settings, synclient, xinput) { 169 | let gsVersion = Lib.executeCmdSync('gnome-shell --version')[1]; 170 | this._builder.get_object('gnome-shell-version').set_label(gsVersion); 171 | 172 | let touchpadEnabled = this._settings.get_boolean('touchpad-enabled').toString(); 173 | this._builder.get_object('touchpadenabled').set_label(touchpadEnabled); 174 | 175 | let sendEvents = settings.get_string('send-events'); 176 | this._builder.get_object('sendevents').set_label(sendEvents); 177 | 178 | let touchpads = xinput._filterByType('touchpad').names.toString(); 179 | this._builder.get_object('touchpads').set_label(touchpads); 180 | 181 | let sessiontype = Lib.SESSION_TYPE; 182 | this._builder.get_object('sessiontype').set_label(sessiontype); 183 | 184 | let switchmethod = this._settings.get_string('switchmethod'); 185 | this._builder.get_object('switchmethod').set_label(switchmethod); 186 | 187 | if (synclient.isUsable) { 188 | let synclientVersion = Lib.executeCmdSync('synclient -V')[1]; 189 | this._builder.get_object('synclient').set_label(synclientVersion); 190 | } 191 | 192 | if (xinput.isUsable) { 193 | let xinputVersion = Lib.executeCmdSync('xinput --version')[1]; 194 | this._builder.get_object('xinput').set_label(xinputVersion); 195 | } 196 | 197 | let debug = this._settings.get_boolean('debug'); 198 | let debugToFile = this._settings.get_boolean('debug-to-file'); 199 | 200 | if (debug) { 201 | this._builder.get_object('debug_to_file_checkbox').set_visible(true); 202 | this._builder.get_object('debug_to_file_checkbox').set_active( 203 | debugToFile); 204 | this._builder.get_object('log_scrolled_window').set_visible( 205 | debugToFile); 206 | this._builder.get_object('log_text_view').set_visible( 207 | debugToFile); 208 | 209 | if (debugToFile) { 210 | this._updateLogView(); 211 | } 212 | } 213 | } 214 | 215 | _updateLogView() { 216 | this._builder.get_object('log_text_buffer').set_text(Lib.readLog()[1], -1); 217 | this._builder.get_object('log_text_view').scroll_to_iter( 218 | this._builder.get_object('log_text_buffer').get_end_iter(), 219 | 0.0, true, 0.5, 1 220 | ); 221 | } 222 | 223 | _populateAboutTab() { 224 | let version = Me.metadata.version; 225 | let releaseTag = `TouchpadIndicator-extensions.gnome.org-v${version}`; 226 | this._builder.get_object('release_linkbutton').set_label(releaseTag); 227 | 228 | let repository = Me.metadata.repository; 229 | let releaseUrl = `${repository}/releases/${releaseTag}`; 230 | this._builder.get_object('release_linkbutton').set_uri(releaseUrl); 231 | } 232 | }; 233 | 234 | function init() { 235 | ExtensionUtils.initTranslations(); 236 | } 237 | 238 | function buildPrefsWidget() { 239 | let settings = new Settings(); 240 | let widget = settings.widget; 241 | widget.show(); 242 | return widget; 243 | } 244 | 245 | 246 | /* exported init buildPrefsWidget*/ -------------------------------------------------------------------------------- /schemas/gschemas.compiled: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/askmrsinh/touchpad-indicator/4af2301297e7225989c9ff7ae4cef3a6cbd47616/schemas/gschemas.compiled -------------------------------------------------------------------------------- /schemas/org.gnome.shell.extensions.touchpad-indicator.gschema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | "gsettings" 11 | 12 | 13 | true 14 | 15 | 16 | 17 | true 18 | 19 | 20 | true 21 | 22 | 23 | false 24 | 25 | 26 | t']]]> 27 | 28 | 29 | 30 | false 31 | 32 | 33 | true 34 | 35 | 36 | 37 | 38 | true 39 | 40 | 41 | true 42 | 43 | 44 | true 45 | 46 | 47 | true 48 | 49 | 50 | true 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /synclient.js: -------------------------------------------------------------------------------- 1 | /* TouchpadIndicator - Touchpad management GNOME Shell Extension. 2 | * Orignal work Copyright (C) 2011-2013 Armin Köhler 3 | * Modifcations Copyright (C) 2019 Ashesh Singh 4 | * 5 | * This file is part of TouchpadIndicator, a fork of Armin Köhler's 6 | * 'gnome-shell-extension-touchpad-indicator' project which is licensed GPLv2. 7 | * Orignal source code is available at https://git.io/fjVec. 8 | * 9 | * This program is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation; either version 2 of the License, or (at your option) 12 | * any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 | * more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * this program; if not, write to: 21 | * The Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor 23 | * Boston, MA 02110-1301, USA. 24 | */ 25 | 26 | const Me = imports.misc.extensionUtils.getCurrentExtension(); 27 | const Lib = Me.imports.lib; 28 | 29 | // Disable Synclient manually to prevent errors 30 | const USE_SYNCLIENT = true; 31 | 32 | function logging(event) { 33 | if (Lib.DEBUG) { 34 | Lib.logger(`Synclient.${event}`); 35 | } 36 | } 37 | 38 | var Synclient = class Synclient { 39 | constructor() { 40 | this._init(); 41 | } 42 | 43 | _init() { 44 | logging('_init()'); 45 | this.isUsable = this._isUsable(); 46 | this.tpdOff = false; 47 | } 48 | 49 | _isUsable() { 50 | if (Lib.SESSION_TYPE.indexOf('wayland') !== -1) { 51 | logging('_isUsable(): ignoring synclient on wayland'); 52 | return false; 53 | } 54 | 55 | if (!USE_SYNCLIENT) { 56 | logging('_isUsable(): synclient manually disabled'); 57 | return false; 58 | } 59 | 60 | let comp = Lib.executeCmdSync('synclient -l'); 61 | if ((comp[1] === undefined) || (comp[0] === false)) { 62 | logging('_isUsable(): synclient not found'); 63 | return false; 64 | } else if (comp[1].includes("Couldn't find synaptics properties")) { 65 | logging('_isUsable(): no properties found'); 66 | return false; 67 | } else if (comp[1].includes('TouchpadOff')) { 68 | logging('_isUsable(): synclient found'); 69 | return true; 70 | } 71 | 72 | logging('_isUsable(): unknown situation - Return false'); 73 | return false; 74 | } 75 | 76 | _disable() { 77 | if (this.isUsable) { 78 | logging('_disable()'); 79 | this.tpdOff = !!Lib.executeCmdAsync('synclient TouchpadOff=1'); 80 | } 81 | } 82 | 83 | _enable() { 84 | if (this.isUsable) { 85 | logging('_enable()'); 86 | this.tpdOff = !!Lib.executeCmdAsync('synclient TouchpadOff=0'); 87 | } 88 | } 89 | 90 | _switch(state) { 91 | logging(`_switch: ${state}`); 92 | if (state) { 93 | return this._enable(); 94 | } else { 95 | return this._disable(); 96 | } 97 | } 98 | }; 99 | 100 | 101 | /* exported Synclient */ -------------------------------------------------------------------------------- /xinput.js: -------------------------------------------------------------------------------- 1 | /* TouchpadIndicator - Touchpad management GNOME Shell Extension. 2 | * Orignal work Copyright (C) 2011-2013 Armin Köhler 3 | * Modifcations Copyright (C) 2019 Ashesh Singh 4 | * 5 | * This file is part of TouchpadIndicator, a fork of Armin Köhler's 6 | * 'gnome-shell-extension-touchpad-indicator' project which is licensed GPLv2. 7 | * Orignal source code is available at https://git.io/fjVec. 8 | * 9 | * This program is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation; either version 2 of the License, or (at your option) 12 | * any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 | * more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * this program; if not, write to: 21 | * The Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor 23 | * Boston, MA 02110-1301, USA. 24 | */ 25 | 26 | const Me = imports.misc.extensionUtils.getCurrentExtension(); 27 | const Lib = Me.imports.lib; 28 | 29 | // Disable Xinput manually to prevent errors 30 | const USE_XINPUT = true; 31 | 32 | function logging(event) { 33 | if (Lib.DEBUG) { 34 | Lib.logger(`XInput.${event}`); 35 | } 36 | } 37 | 38 | var XInput = class XInput { 39 | constructor() { 40 | this._init(); 41 | } 42 | 43 | _init() { 44 | logging('_init()'); 45 | this.isUsable = this._isUsable(); 46 | if (!this.isUsable){ 47 | return; 48 | } 49 | this.pointingDevices = this._listPointingDevices()[1]; 50 | } 51 | 52 | _isUsable() { 53 | if (Lib.SESSION_TYPE.indexOf('wayland') !== -1) { 54 | logging('_isUsable(): ignoring xinput on wayland'); 55 | return false; 56 | } 57 | 58 | if (!USE_XINPUT) { 59 | logging('_isUsable(): xinput manually disabled'); 60 | return false; 61 | } 62 | 63 | let comp = Lib.executeCmdSync('xinput --list'); 64 | if ((comp[1] === undefined) || (comp[0] === false)) { 65 | logging('_isUsable(): xinput not found'); 66 | return false; 67 | } else if (comp[1].includes("Virtual core pointer")) { 68 | logging('_isUsable(): xinput found'); 69 | return true; 70 | } 71 | 72 | logging('_isUsable(): unknown situation - Return false'); 73 | return false; 74 | } 75 | 76 | _listPointingDevices() { 77 | let pointingDevices = []; 78 | let comp = Lib.executeCmdSync('xinput --list'); 79 | let allDeviceLines = comp[1].split('\n'); 80 | let x = 0; 81 | //assuming that 'pointer' lines always appear fist & together 82 | while (allDeviceLines[x].includes('pointer')) { 83 | if (allDeviceLines[x].indexOf('Virtual') === -1) { 84 | let pointingDeviceLine = allDeviceLines[x]; 85 | let pointingDevice = this._makePointingDevice(pointingDeviceLine); 86 | if (pointingDevice !== undefined) { 87 | pointingDevices.push(pointingDevice); 88 | } 89 | } 90 | x++; 91 | } 92 | if (pointingDevices[0]) { 93 | return [true, pointingDevices]; 94 | } else { 95 | return [false, ' - No Pointing Devices detected.\n']; 96 | } 97 | } 98 | 99 | _makePointingDevice(pointingDeviceLine) { 100 | let pointingDevice = {}; 101 | let id = pointingDeviceLine.split('id=')[1].split('\t')[0]; 102 | let name = Lib.executeCmdSync(`xinput --list --name-only ${id}`)[1]; 103 | for (let type in Lib.ALL_TYPES) { 104 | if (Lib.ALL_TYPES[type].some((t) => { 105 | return (name.toLowerCase().indexOf(t) >= 0); 106 | })) { 107 | pointingDevice.id = id; 108 | pointingDevice.name = name; 109 | pointingDevice.type = type; 110 | pointingDevice.driver = this._getDriver(pointingDevice.id); 111 | // eslint-disable-next-line prefer-template 112 | logging('_makePointingDevice(...): Found ' + pointingDevice.type + 113 | ', Id="' + pointingDevice.id + '"' + 114 | ', Name="' + pointingDevice.name + '"' + 115 | ', Driver="' + pointingDevice.driver + '"'); 116 | return pointingDevice; 117 | } 118 | } 119 | } 120 | 121 | _enableAll() { 122 | if (this.isUsable) { 123 | logging('_enableAll()'); 124 | for (let i = 0; i < this.pointingDevices.length; ++i) { 125 | let id = this.pointingDevices[i].id; 126 | Lib.executeCmdAsync(`xinput set-prop ${id} "Device Enabled" 1`); 127 | } 128 | } 129 | } 130 | 131 | _enableByType(deviceType) { 132 | let ids = this._filterByType(deviceType).ids; 133 | return this._enable(ids); 134 | } 135 | 136 | _disableByType(deviceType) { 137 | let ids = this._filterByType(deviceType).ids; 138 | return this._disable(ids); 139 | } 140 | 141 | _switchByType(deviceType, state) { 142 | logging(`_switchByType(${deviceType}, ${state})`); 143 | if (state) { 144 | this._enableByType(deviceType); 145 | } else { 146 | this._disableByType(deviceType); 147 | } 148 | } 149 | 150 | _enable(ids) { 151 | if (this.isUsable) { 152 | logging(`_enable(${ids})`); 153 | for (let i = 0; i < ids.length; ++i) { 154 | Lib.executeCmdAsync(`xinput set-prop ${ids[i]} "Device Enabled" 1`); 155 | } 156 | } 157 | } 158 | 159 | _disable(ids) { 160 | if (this.isUsable) { 161 | logging(`_disable(${ids})`); 162 | for (let i = 0; i < ids.length; ++i) { 163 | Lib.executeCmdAsync(`xinput set-prop ${ids[i]} "Device Enabled" 0`); 164 | } 165 | } 166 | } 167 | 168 | _filterByType(deviceType) { 169 | let ids = []; 170 | let names = []; 171 | let drivers = []; 172 | 173 | if (this.isUsable) { 174 | let filteredPointingDevices = this.pointingDevices.filter((d) => { 175 | return (d.type === deviceType); 176 | }); 177 | for (let i = 0; i < filteredPointingDevices.length; i++) { 178 | ids.push(filteredPointingDevices[i].id); 179 | names.push(filteredPointingDevices[i].name); 180 | drivers.push(filteredPointingDevices[i].driver); 181 | } 182 | } 183 | 184 | return { 'ids': ids, 'names': names, 'drivers': drivers }; 185 | } 186 | 187 | _isPresent(deviceType) { 188 | let ids = this._filterByType(deviceType).ids; 189 | let isPresent = (ids.length > 0); 190 | logging(`_isPresent(${deviceType}): ${isPresent}`); 191 | return isPresent; 192 | } 193 | 194 | _getDriver(id) { 195 | let properties = Lib.executeCmdSync(`xinput --list-props ${id}`)[1]; 196 | if (properties.includes('libinput')) { 197 | return 'libinput'; 198 | } else if (properties.includes('Synaptics')) { 199 | return 'Synaptics'; 200 | } 201 | return 'other'; 202 | } 203 | }; 204 | 205 | 206 | /* exported XInput */ --------------------------------------------------------------------------------