pax_global_header00006660000000000000000000000064141544453270014523gustar00rootroot0000000000000052 comment=855b64d2bd92e9f570e55886c163fa15972269fd screenkey-v1.5/000077500000000000000000000000001415444532700135465ustar00rootroot00000000000000screenkey-v1.5/.gitignore000066400000000000000000000000731415444532700155360ustar00rootroot00000000000000*[#~] *.py[co] /*.egg-info /.eggs/ *.pot *.mo /dist /build screenkey-v1.5/COPYING.txt000066400000000000000000001045131415444532700154230ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . screenkey-v1.5/NEWS.rst000066400000000000000000000133041415444532700150550ustar00rootroot00000000000000screenkey 1.5 ------------- - New LockScreen detection from Marc Lavallée prevents passwords from being shown right after unlocking the screen when possible (new ``dbus`` dependency required). - Keypad number keys are now displayed correctly (thanks to @Gordin508). - Additional mouse buttons are now shown as "M[x]" instead of being incorrectly displayed as Ctrl/Alt modifiers (@Gordin508). - The new ``--window`` command line flag allows to display screenkey as a regular window instead of an overlay. This can be useful for recording screenkey as an independent overlay during screencasts and/or to manage the window position through the window manager. - New German translation thanks to Maik Schmalle. - Fix regression that would keep the overlay visible when using Ctrl sequences with the mouse visualization disabled. - Fix regression causing a backtrace instead of a proper error message during initialization errors. - Fix crash happening due to screen size and/or resolution changes while screenkey is running. - Prettify JSON configuration file (thanks to Mehrad Mahmoudian). screenkey 1.4 ------------- - Internationalization/catalog handling during installation is now handled with Babel (``python-distutils-extra`` is no longer used). - Improved highlighting of recent mouse activity (makes fast actions such as double-click more distinct). - Fixed another resizing issue not working properly when attempting to shrink the window size. - Removed Python 2 remains (thanks to Jürgen Gmach). screenkey 1.3 ------------- - Can displays mouse clicks and modifier keys, with big thanks to Matthew White, Ziad El Khoury Hanna and Roope Salmi! - Updated Russian translation thanks to Olesya Gerasimenko. - Includes Appstream metadata by Rajeesh K V. - Add ``--version`` support by Anders Jackson. - Fixes interactive resizing with a persistent window. screenkey 1.2 ------------- - Now supports FontAwesome 5 in addition to FontAwesome 4. - New multimedia keys for: bluetooth, tools, favorites. - New Catalan translation thanks to Eduard Ereza Martínez. - Updated Simplified Chinese translation by @WhiredPlanck. - New flag ``--start-disabled`` by Laurence Tratt to start screenkey in disabled state. - Fix crash due to a race condition thanks to Roope Salmi. - Fix incorrect value for "Compress repeats" in settings. screenkey 1.1 ------------- - Fix PyGI warning during startup when using AppIndicator. - Fix running with GTK versions older than 3.23. screenkey 1.0 ------------- - Switch to Python 3 and GTK 3, thanks to Yuto Tokunaga. - "ISO_Left_Tab" is now also shown as Tab. - Shift+Shift or Alt+Alt can now be used to toggle screenkey as an alternative to Ctrl+Ctrl. - More multimedia keys are supported (volume, brightness, playback). - Transparency of the window is now independent from the text (thanks to Ziad EL KHOURY HANNA) - Screenkey no longer detaches by default from the terminal. - New "Windows" and "Linux" modifier modes. - French Translation improvements by Georges Khaznadar. - Improved geometry handling by Alberto Fanjul. screenkey 0.9 ------------- - Ctrl+Ctrl detection now works correctly in more scenarios. - Ctrl++ (and similar sequences with repeated characters) are now shown as Ctrl+"+" for improved readability. - Shift+Backspace is now recognized and shown correctly. - Several multimedia keys are now supported. If "FontAwesome" is installed, the correct symbol is also displayed instead of a text abbreviation. - Visualization of whitespace characters can now be controlled. - Repeated key sequences are now abbreviated with a repeat count if above the specified threshold (3 by default). screenkey 0.8.1 --------------- - Fixed startup issue in Ubuntu without using ``--no-detach``. - Fixed desktop menu file. screenkey 0.8 ------------- - Fix Alt+Shift mapping on stock altgr-intl keyboard layouts. - Correctly stay above fullscreen windows. - Do not mask pointer/keyboard events: allow the mouse to be used normally "under" the output window. - Improved interactive positioning (slop is required). - Allow KeySyms to be ignored (added ``--ignore`` on the command line), for better interaction with custom keyboard maps. screenkey 0.7 ------------- - Font color, background color and opacity are now fully configurable. - The saved state of boolean settings (persistent, modifiers only, etc) is correctly restored when changed from the settings dialog. screenkey 0.6.2 --------------- - HiDPI support - Fix initial state of "Persistent window" in the preferences. - Allow to reset the stored the geometry from the preferences also when changed interactively. screenkey 0.6.1 --------------- - Fix exception on first run. screenkey 0.6 ------------- - The ``python-xlib`` module and the ``xmodmap`` executable are not required/used anymore. screenkey now uses ``libX11.so.6`` directly. - Key composition/input method support. - A new setting (always show Shift) has been added to always add "Shift" in modifier sequences which contain capitalizable letters. - CapsLock and NumLock status (on/off) is now shown when pressed. screenkey 0.5 ------------- - Fixes issues with recent ``glib`` versions. - ``XAUTHORITY`` is no longer required to be set. screenkey 0.4 ------------- - The font is now configurable as well - Tweaks to symbol spacing - Highlight recent keypresses for improved readability screenkey 0.3 ------------- - Multi-monitor support - Configurable size/position - Can show modifier sequences only - Improved backspace processing (3 different modes) - Normal/Emacs/Mac caps modes - Enable/disable dynamically by pressing both control keys - All settings available through command-line flags - Usable without system tray (for tiling window managers) - Several bug fixes screenkey-v1.5/README.rst000066400000000000000000000433031415444532700152400ustar00rootroot00000000000000===================== Screencast your keys. ===================== .. contents:: A screencast tool to display your keys, inspired by Screenflick_. This is an almost-complete rewrite of screenkey_ 0.2, featuring: - Several keyboard translation methods - Key composition/input method support - Configurable font/size/position - Highlighting of recent keystrokes - Improved backspace processing - Normal/Emacs/Mac caps modes - Multi-monitor support - Dynamic recording control - Switch for visible shift and modifier sequences only - Repeats compression - Countless bug fixes - Mouse buttons support Installation and basic usage ---------------------------- Official packages ~~~~~~~~~~~~~~~~~ Arch: `Arch community package `_ ``sudo pacman -S screenkey`` Debian / Ubuntu: `Debian tracker `_ ``sudo apt-get install screenkey`` Fedora / EPEL: `Fedora package `_ ``sudo dnf install screenkey`` Gentoo: `Gentoo package `_ ``sudo emerge -av x11-misc/screenkey`` Screenkey is available on `other distributions `_ too. From source ~~~~~~~~~~~ Execute without installation:: ./screenkey To install:: sudo ./setup.py install Dependencies: - Python 3.x (Python 2.x is no longer supported) - PyGObject (python3-gi) - GTK 3 (via GI bindings) - Pycairo (python3-cairo) - Cairo GI bindings (python3-gi-cairo) - Python DBUS (python3-dbus) - setuptools (python3-setuptools, build only) - babel (python3-babel, build only) - slop (https://github.com/naelstrof/slop) - FontAwesome_ (for multimedia symbols) - GIR AppIndicator (only required for Unity / GNOME Shell) Install dependencies (on Debian/Ubuntu):: sudo apt-get install python3-gi gir1.2-gtk-3.0 sudo apt-get install python3-gi-cairo python3-cairo sudo apt-get install python3-setuptools python3-babel sudo apt-get install python3-dbus fonts-font-awesome slop When using GNOME also install:: sudo apt-get install gir1.2-appindicator3-0.1 Note: Screenkey makes use of low-level X11 functions directly via ``libX11.so.6``. Settings -------- Display time: Persistence (in seconds) of the output window after typing has stopped. Defaults to 2.5 seconds. When the window is persistent, display time still controls the time before the text is cleared. Persistent window: Forces the output window to be always visible, irregardless of typing activity. Mostly useful for interactive window placement and/or "fixed" positioning. Screen: Physical screen/monitor used for the output window. Position: Position of the output window. The position is normally relative to the chosen screen. If a window has been selected with "Select window/region", the position becomes relative to the window. If "fixed" is chosen, the output window's position and size are specified explicitly. See `Interactive placement`_ for more details. Font: Font used for the output window. A scalable font and wide Unicode coverage is required (the DejaVu family is *highly* recommended). Size: Size of the font used in the output window. Chooses proportionally between 8/12/24% of the screen size. When "fixed" positioning is used, size is ignored and the font will fill the available height of the output window. Keyboard mode: Choose the translation method of keyboard events. "Composed" attempts to show only the final results of key composition. Dead keys and any intermediate output during composition is not shown. Currently works correctly with XIM/IBUS, but only for on-the-spot editing. It can cause problems with complex input methods (support for wider compatibility is underway). "Translated" shows the result of each keypress on the keyboard, accounting for the current keyboard locale and modifiers, but not composition. Pressing a dead key followed by a letter will show both keys. "Raw" shows which key caps were pressed on the keyboard, without translation. For example, typing "!" (which is often located on top of the key "1") requires pressing "Shift+1", which is what this output mode shows. "Backspace mode", "Always visible Shift" and "Modifiers only" have no effect in this mode. "Keysyms" shows the keysyms ("symbolic" names) of each pressed key as received by the server. Mostly useful for debugging. Backspace mode: Controls the effect of "backspace" on the text in the output window. "Normal" always inserts a backspace symbol in the output window. "Baked" simulates the effect of backspace in the text only if the last keypress is a regular letter and no caret movement has been detected. In any other case, a backspace symbol is inserted instead. "Full" is similar to "baked", but will eat through several other, less safe keys, such as tabs and returns. Modifiers mode: Select how modifiers keys (such as Control, Alt) are displayed in the output window. "Normal" uses traditional PC names (Ctrl+A) while "Mac" uses Mac symbols directly (⌘+A). The "Emacs" mode will display Emacs-style shortened keyboard sequences (C-A). Show Modifier sequences only: Only show modifier/control sequences in the output window. Bare, shifted or translated letters are not shown. Always show Shift: Shift is normally hidden when the control sequence includes a letter that can differentiate between a shifted/non-shifted key. For example, Shift + "Control+a" is normally shown just as "Control+A" (notice the capital "A"). When "Always show Shift" is used, Shift is always included in modifier sequences, if pressed. Has no effect when using the "Emacs" modifiers mode. Show Whitespace characters: Convert regular whitespace characters (tabs and spaces) to a visible representation instead of showing a blank. Newlines are also hidden when unambiguous in multiline mode. Compress repeats: When enabled, contiguous repeated sequences are truncated after the requested threshold. A counter of total occurrences is shown instead, which is generally more legible. Show mouse: When enabled, the mouse buttons are shown on the left of the output window. Hide duration: Duration (in seconds) of the fade-out animation when a button is released. Defaults to 1 second. Advanced usage -------------- Controlling visibility ~~~~~~~~~~~~~~~~~~~~~~ To disable screenkey while recording (for example, during password prompts), press both control keys, or both shift keys, or both alt keys at the same time. Press the same combination again to resume it. This has the same effect of toggling the state from the system tray icon, but it's completely stealth: there's no feedback that screenkey is being switched on/off. If you need the viewer to focus on a sentence you just typed, you can press a silent modifier (such as Shift, or Control) to keep the output window visible a little longer without prolonging the default timeout. Interactive placement ~~~~~~~~~~~~~~~~~~~~~ screenkey is normally positioned on the top/center/bottom part of the screen. If you're recording a screencast only for a specific application, you can click on "Select window/region" to select on which window the output should be overlaid (slop_ must be installed for this task). When a window has been selected, top/center/bottom refer to the window's contents. Press "Reset" to restore the original behavior. When "fixed" is chosen, the position of the output is specified *directly*. The cursor turns immediately into a crossbar: drag over the desired screen region (where the text should appear), or press "Esc" to abort. Again, press "Reset" to restore the original behavior. Command-line placement ~~~~~~~~~~~~~~~~~~~~~~ The "geometry" argument follows the standard X11 geometry format (``WxH[+X+Y]``) and can be provided by slop_, which allows to select windows and/or drag over the desired region interactively without the need of calculating the coordinates manually. When a geometry argument has been provided, the position (top/middle/bottom) becomes relative to the selected rectangle. For example, to overlay screenkey on top of an existing window, you can simply do:: ./screenkey -g $(slop -n -f '%g') To set the actual text rectangle instead, use "fixed" positioning. Using slop, you can combine both and simply drag the desired rectangle during selection:: ./screenkey -p fixed -g $(slop -n -f '%g') X and Y coordinates can be negative and in such cases they refer to a distance from opposite side of the screen (+10 would be 10 pixels from the left side of the screen, while -10 being 10 pixels from the right). As an extension to the geometry format, all numbers can be written with a trailing % to refer as a percentage to the selected screen size. For example, the following:: ./screenkey -p fixed -g 90%x10%+5%-10% specifies an horizontally centered rectangle filling 90% of the width of screen at 10% from the bottom. Choosing a good font ~~~~~~~~~~~~~~~~~~~~ The default font is "Sans Bold", which is usually mapped to "DejaVu Sans" on most Linux installations (look for the ``ttf-dejavu`` package). It's a good all-around font which provides all the required glyphs and has *excellent* readability. For screencasts about programming, we recommend "DejaVu Sans Mono Bold" instead, which provides better differentiation among similar letterforms (0/O, I/l, etc). Multimedia keys ~~~~~~~~~~~~~~~ "screenkey" supports several multimedia keys. To display them with symbols instead of text abbreviations, FontAwesome_ needs to be installed. On Debian/Ubuntu, the font is available in the ``fonts-font-awesome`` package. On Arch Linux the package is instead ``ttf-font-awesome``. .. _FontAwesome: http://fontawesome.io/ Tiling window managers ~~~~~~~~~~~~~~~~~~~~~~ "screenkey" should work correctly by default with any tiling window manager. The original version of screenkey used to require customization for the output window to work/float correctly. These settings are *no longer required* with this fork, and can be safely removed. If you don't have a system tray, you can either configure screenkey through command line flags or use ``--show-settings`` to test the configuration interactively. To get transparency you need a compositor to be running. For example, "compton" or "unagi" are popular for their low impact on performance, but "xcompmgr" also works correctly without any additional configuration. Related tools ~~~~~~~~~~~~~ When doing screencasts involving a lot of mouse activity, or which require holding down modifiers to perform other mouse actions, key-mon_ (Python-based) or the newer kmcaster_ (Java-based) might be a good companion to screenkey, or replace it entirely. Both can be configured to show the state of key modifiers continuously and circle the location of mouse clicks ("visible click") and can be used together with screenkey. Troubleshooting --------------- Initialization failure ~~~~~~~~~~~~~~~~~~~~~~ Screenkey is very sensitive to improperly configured input methods or keyboard settings. Installing, removing or "playing around" with some packages such as ``im-config``, ``ibus``, ``fcitx`` or ``scim`` might leave the current settings in a half-broken state. Some distributions are also known to have broken settings by *default*. In short: the various environment flags (``XMODIFIERS``, ``GTK_IM_MODULE``, ``QT_IM_MODULE`` to name a few) need to be *consistent*. They either should be all unset, or all set to the *same* input method. When using ``ibus``, ``fcitx`` or other complex methods, the corresponding daemon *must* be running. An "input method" is the mechanism which handles the task of transforming key presses into characters. Latin languages mostly use a straightforward key -> character mechanism, but other languages don't have a key for each possible character and thus need extra logic. Programs need to be told *which* input method to use, and this is usually done through environment variables. There is one environment variable for each graphical toolkit and it's set at the start of the session, usually by a command in the ``~/.profile`` file. Screenkey can only record a program correctly if it's using the *same* input method as the target. To check the status of the environment, run the following inside a terminal:: echo XMODIFIERS=$XMODIFIERS echo GTK_IM_MODULE=$GTK_IM_MODULE echo QT_IM_MODULE=$QT_IM_MODULE On a system with a Latin language and without any complex input method running you should see everything empty:: XMODIFIERS= GTK_IM_MODULE= QT_IM_MODULE= On a system running "ibus" you should see:: XMODIFIERS=@im=ibus GTK_IM_MODULE=ibus QT_IM_MODULE=ibus Additionally, the ibus package must be installed and the ibus daemon should be running. Check the output of:: $ pgrep -ax ibus-daemon 982 /usr/bin/ibus-daemon --xim ``ibus-daemon`` should be present and *must* include ``--xim`` in the command line. If not, the daemon must be restarted with it! Consult the documentation of your distribution for more information. On a system using "fcitx" the following output has to be expected:: XMODIFIERS=@im=fcitx GTK_IM_MODULE=fcitx QT_IM_MODULE=fcitx In this case ``fcitx`` daemon should be running as well:: $ pgrep -ax fcitx 1053 /usr/bin/fcitx If you see *any* mixture of the above, your system is likely to be incorrectly configured. If the "ibus" or "fcitx" packages are not installed, there are no daemons running and the variables are mostly empty, then try simply unsetting all of them before running Screenkey in a terminal:: unset XMODIFIERS unset GTK_IM_MODULES unset QT_IM_MODULES screenkey If screenkey runs correctly after these changes, check your startup files such as ``~/.profile``, ``~/.bash_profile`` or ``~/.pam_environment`` and remove the offending variables to make the change permanent. You must log-out and log-in in order to be able to run Screenkey normally after the change. If you're running either ``ibus`` or ``fcitx`` but the variables contain mixed values, try to reset them manually using:: export XMODIFIERS=@im=ibus export GTK_IM_MODULE=ibus export QT_IM_MODULE=ibus screenkey Again, if Screenkey works correctly after the change, inspect the contents of your startup files as above to make the change permanent. You should always check the documentation of your distribution to see which input method *should* be running and how it should be configured. The above guide is not meant to be exhaustive. If nothing works, get in touch with the authors or file an issue on Gitlab to get more help. Cannot stop Screenkey or no status icon ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can exit from Screenkey by right-clicking on it's status icon and selecting "Quit". If you're using GNOME/Unity and cannot see any status icon please make sure the ``gir1.2-appindicator3-0.1`` package is installed. Run the following inside a terminal to install as required:: sudo apt-get install gir1.2-appindicator3-0.1 On any other desktop system Screenkey uses the regular system tray. If you don't have a systray or you cannot quit an existing Screenkey, use the following command in a terminal to kill it:: pkill -f screenkey The proper way to exit when running Screenkey from a terminal is simply by interrupting it with ``Ctrl+C``. No output in GNOME Terminal ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Screenkey cannot currently capture any input directed to native Wayland programs such as the GNOME Terminal: only X11 programs are supported. If you need to record a terminal session you'll have to switch to another X11 terminal emulator such as xterm, urxvt, mlterm, ... Localization ------------ Adding a new language translation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ After cloning the source repository, initialize a fresh new localization as following:: ./setup.py extract_messages ./setup.py init_catalog -l Where ```` is the locale name such as ``de_DE``. The generated template is located in ``Screenkey/locale//LC_MESSAGES/screenkey.po`` and can be edited with a text editor or using a PO editing tool such as poedit_. .. _poedit: https://poedit.net/ Updating an existing translation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To update a pre-exiting language translation, execute:: ./setup.py extract_messages ./setup.py update_catalog -l then review the updated localization in ``Screenkey/locale//LC_MESSAGES/screenkey.po``. Testing a translation ~~~~~~~~~~~~~~~~~~~~~ Localization can be tested by compiling the language catalog and running ``screenkey`` from the source directory:: ./setup.py compile_catalog -l ./screenkey The catalog needs to be compiled every time the localization has been changed to reflect the newest changes. Authors and Copyright --------------------- "screenkey" can be found at https://www.thregr.org/~wavexx/software/screenkey/ | "screenkey" is distributed under GNU GPLv3+, WITHOUT ANY WARRANTY. | Copyright(c) 2010-2012: Pablo Seminario | Copyright(c) 2015-2021: wave++ "Yuri D'Elia" | Copyright(c) 2019-2020: Yuto Tokunaga screenkey's GIT repository is publicly accessible at: https://gitlab.com/screenkey/screenkey Additional Thanks ----------------- * @logix (gitlab) * @rhoit (github) * Alberto Fanjul * Benjamin Chrétien * Dmitry Bushev * Doug Patti * Farrer (launchpad) * Georges Khaznadar * Igor Bronovskyi * Ivan Makfinsky * Jacob Gardner * Matthew White * Muneeb Shaikh * Olivier Boesch * Stanislav Seletskiy * Zhum (launchpad) * Ziad El Khoury Hanna * 伊冲 .. _Screenflick: http://www.araelium.com/screenflick/ .. _key-mon: https://code.google.com/p/key-mon/ .. _kmcaster: https://github.com/DaveJarvis/kmcaster/ .. _screenkey: https://launchpad.net/screenkey .. _slop: https://github.com/naelstrof/slop screenkey-v1.5/Screenkey/000077500000000000000000000000001415444532700154765ustar00rootroot00000000000000screenkey-v1.5/Screenkey/__init__.py000066400000000000000000000034541415444532700176150ustar00rootroot00000000000000try: from collections.abc import MutableMapping except ImportError: # for python<3.3 from collections import MutableMapping # Setup gettext import os.path import gettext MODULE_DIR = os.path.join(os.path.dirname(__file__)) gettext.install('screenkey', os.path.join(MODULE_DIR, 'locale')) # Screenkey version APP_NAME = "Screenkey" APP_DESC = _("Screencast your keys") APP_URL = 'https://www.thregr.org/~wavexx/software/screenkey/' VERSION = '1.5' SLOP_URL = 'https://github.com/naelstrof/slop' ERROR_URL = 'https://www.thregr.org/~wavexx/software/screenkey/#troubleshooting' # CLI/Interface options POSITIONS = { 'top': _('Top'), 'center': _('Center'), 'bottom': _('Bottom'), 'fixed': _('Fixed'), } FONT_SIZES = { 'large': _('Large'), 'medium': _('Medium'), 'small': _('Small'), } KEY_MODES = { 'composed': _('Composed'), 'translated': _('Translated'), 'keysyms': _('Keysyms'), 'raw': _('Raw'), } BAK_MODES = { 'normal': _('Normal'), 'baked': _('Baked'), 'full': _('Full'), } MODS_MODES = { 'normal': _('Normal'), 'emacs': _('Emacs'), 'mac': _('Mac'), 'win': _('Windows'), 'tux': _('Linux'), } class Options(MutableMapping): def __init__(self, *args, **kw): self.__dict__['_store'] = dict(*args, **kw) def __getitem__(self, key): return self._store[key] def __setitem__(self, key, value): self._store[key] = value def __delitem__(self, key): del self._store[key] def __iter__(self): return iter(self._store) def __len__(self): return len(self._store) def __getattr__(self, key): return self._store[key] def __setattr__(self, key, value): self._store[key] = value def __delattr__(self, key): del self._store[key] screenkey-v1.5/Screenkey/images/000077500000000000000000000000001415444532700167435ustar00rootroot00000000000000screenkey-v1.5/Screenkey/images/mouse.original.svg000066400000000000000000000333501415444532700224230ustar00rootroot00000000000000 image/svg+xml screenkey-v1.5/Screenkey/images/mouse.svg000066400000000000000000000124001415444532700206110ustar00rootroot00000000000000 screenkey-v1.5/Screenkey/inputlistener.py000066400000000000000000000366721415444532700207730ustar00rootroot00000000000000# Distributed under the GNU GPLv3+ license, WITHOUT ANY WARRANTY. # Copyright(c) 2015: wave++ "Yuri D'Elia" # # Outputting translated X11 keystrokes is not a simple problem as soon as XIM # is introduced: getting an updated keyboard/modifier map is not enough to # replicate the [complex] logic hidden in the input method. # # For this reason we use a fairly convoluted mechanism: we record keystrokes # using the XRecord extension, but we relay them to another fake window running # on the same server. By manipulating the event, we trick the input method to # perform composition for us, and poll for translated output events using # Xutf8LookupString. Since we cannot determine the state of the input context # for the target window (we're recording blindly), we also need to reset # context state carefully when the user switches the active focus. 3(!) extra # connections to the display server are required for this task, and since we're # using blocking APIs, having to run on our own thread means we cannot share # any of those with the regular process. On the other hand, many other keycode # translation issues are avoided by using the string lookup directly. # # This is, of course, never going to be always identical to the final output, # since we're guessing the state of the client (we do the same when guessing # the result of backspace anyway). But incidentally this method would also # allow us to poll the input mechanism while composing, to better reflect the # actual typing on the keyboard. # # Some of the code /could/ have been simplified by using XCB for protocol # translation, but since there's no equivalent to XKB/XIM, I found the exercise # futile. Needing to use XIM directly also barred pure-python equivalents. As # a result, we have to drop back to ctypes for _extra_ phun. # # Drop me a line if you ever find this comment helpful, as finding a decent # solution was not trivial -- YD 21/08/2015. if __name__ == '__main__': import xlib import keysyms else: from . import xlib from . import keysyms import sys if sys.version_info.major < 3: import glib else: from gi.repository import GLib as glib import threading import warnings import select # convenience wrappers def coalesce_ranges(ranges): ranges = sorted(ranges, key=lambda x: x[0]) ret = ranges[:1] for r in ranges[1:]: if ret[-1][1] < r[0] - 1: ret.append(r) else: ret[-1][1] = max(ret[-1][1], r[1]) return ret def record_context(dpy, ev_ranges, dev_ranges): ev_ranges = coalesce_ranges(ev_ranges) dev_ranges = coalesce_ranges(dev_ranges) specs = max(len(ev_ranges), len(dev_ranges)) range_specs = (xlib.POINTER(xlib.XRecordRange) * specs)() for i in range(specs): range_specs[i] = xlib.XRecordAllocRange() if len(ev_ranges) > i: range_specs[i].contents.delivered_events.first = ev_ranges[i][0] range_specs[i].contents.delivered_events.last = ev_ranges[i][1] if len(dev_ranges) > i: range_specs[i].contents.device_events.first = dev_ranges[i][0] range_specs[i].contents.device_events.last = dev_ranges[i][1] rec_ctx = xlib.XRecordCreateContext( dpy, 0, xlib.byref(xlib.c_ulong(xlib.XRecordAllClients)), 1, range_specs, specs) for i in range(specs): xlib.XFree(range_specs[i]) return rec_ctx def record_enable(dpy, rec_ctx, callback): def intercept(data): if data.category != xlib.XRecordFromServer: return if data.client_swapped: warnings.warn("cannot handle swapped protocol data") return ev = xlib.XWireToEvent(dpy, data.data) callback(ev) def intercept_(_, data): intercept(data.contents) xlib.XRecordFreeData(data) proc = xlib.XRecordInterceptProc(intercept_) xlib.XRecordEnableContextAsync(dpy, rec_ctx, proc, None) return proc def create_replay_window(dpy): win_attr = xlib.XSetWindowAttributes() win_attr.override_redirect = True win = xlib.XCreateWindow(dpy, xlib.XDefaultRootWindow(dpy), 0, 0, 1, 1, 0, xlib.CopyFromParent, xlib.InputOnly, None, xlib.CWOverrideRedirect, xlib.byref(win_attr)) return win def phantom_release(dpy, kev): if not xlib.XPending(dpy): return False ev = xlib.XEvent() xlib.XPeekEvent(dpy, xlib.byref(ev)) return (ev.type == xlib.KeyPress and \ ev.xkey.state == kev.state and \ ev.xkey.keycode == kev.keycode and \ ev.xkey.time == kev.time) def keysym_to_unicode(keysym): if 0x01000000 <= keysym <= 0x0110FFFF: return unichr(keysym - 0x01000000) keydata = keysyms.KEYSYMS.get(keysym) if keydata is not None: return keydata[0] return None class KeyData(): def __init__(self, pressed=None, filtered=None, repeated=None, string=None, keysym=None, status=None, symbol=None, mods_mask=None, modifiers=None): self.pressed = pressed self.filtered = filtered self.repeated = repeated self.string = string self.keysym = keysym self.status = status self.symbol = symbol self.mods_mask = mods_mask self.modifiers = modifiers class ButtonData(): def __init__(self, btn, pressed): self.btn = btn self.pressed = pressed == xlib.ButtonPress class InputType: keyboard = 0b001 button = 0b010 movement = 0b100 all = 0b111 class InputListener(threading.Thread): def __init__(self, event_callback, input_types=InputType.all, kbd_compose=True, kbd_translate=True): super().__init__() self.event_callback = event_callback self.input_types = input_types self.kbd_compose = kbd_compose self.kbd_translate = kbd_translate self.lock = threading.Lock() self.stopped = True self.error = None def _event_received(self, ev): if xlib.KeyPress <= ev.type <= xlib.MotionNotify: xlib.XSendEvent(self.replay_dpy, self.replay_win, False, 0, ev) elif ev.type in [xlib.FocusIn, xlib.FocusOut]: # Forward the event as a custom message in the same queue instead # of resetting the XIC directly, in order to preserve queued events fwd_ev = xlib.XEvent() fwd_ev.type = xlib.ClientMessage fwd_ev.xclient.message_type = self.custom_atom fwd_ev.xclient.format = 32 fwd_ev.xclient.data[0] = ev.type xlib.XSendEvent(self.replay_dpy, self.replay_win, False, 0, fwd_ev) def _event_callback(self, data): self.event_callback(data) return False def _event_processed(self, data): data.symbol = xlib.XKeysymToString(data.keysym) if data.string is None: data.string = keysym_to_unicode(data.keysym) glib.idle_add(self._event_callback, data) def _event_modifiers(self, kev, data): data.modifiers = modifiers = {} modifiers['shift'] = bool(kev.state & xlib.ShiftMask) modifiers['caps_lock'] = bool(kev.state & xlib.LockMask) modifiers['ctrl'] = bool(kev.state & xlib.ControlMask) modifiers['alt'] = bool(kev.state & xlib.Mod1Mask) modifiers['num_lock'] = bool(kev.state & xlib.Mod2Mask) modifiers['hyper'] = bool(kev.state & xlib.Mod3Mask) modifiers['super'] = bool(kev.state & xlib.Mod4Mask) modifiers['alt_gr'] = bool(kev.state & xlib.Mod5Mask) def _event_keypress(self, kev, data): buf = xlib.create_string_buffer(16) keysym = xlib.KeySym() status = xlib.Status() ret = xlib.Xutf8LookupString(self._kbd_replay_xic, kev, buf, len(buf), xlib.byref(keysym), xlib.byref(status)) if ret != xlib.NoSymbol: if 32 <= keysym.value <= 126: # avoid ctrl sequences, just take the character value data.string = chr(keysym.value) else: try: data.string = buf.value.decode('utf-8') except UnicodeDecodeError: pass data.keysym = keysym.value data.status = status.value def _event_lookup(self, kev, data): # this is mostly for debugging: we do not account for group/level data.keysym = xlib.XkbKeycodeToKeysym(kev.display, kev.keycode, 0, 0) def start(self): self.lock.acquire() self.stopped = False self.error = None super().start() def stop(self): with self.lock: if not self.stopped: self.stopped = True xlib.XRecordDisableContext(self.control_dpy, self.record_ctx) def _kbd_init(self): self._kbd_last_ev = xlib.XEvent() if self.kbd_compose: style = xlib.XIMPreeditNothing | xlib.XIMStatusNothing else: style = xlib.XIMPreeditNone | xlib.XIMStatusNone # TODO: implement preedit callbacks for on-the-spot composition # (this would fix focus-stealing for the global IM state) self._kbd_replay_xim = xlib.XOpenIM(self.replay_dpy, None, None, None) if not self._kbd_replay_xim: raise Exception("Cannot initialize input method") self._kbd_replay_xic = xlib.XCreateIC(self._kbd_replay_xim, xlib.XNClientWindow, self.replay_win, xlib.XNInputStyle, style, None) xlib.XSetICFocus(self._kbd_replay_xic) def _kbd_del(self): xlib.XDestroyIC(self._kbd_replay_xic) xlib.XCloseIM(self._kbd_replay_xim) def _kbd_process(self, ev): if ev.type == xlib.ClientMessage and \ ev.xclient.message_type == self.custom_atom: if ev.xclient.data[0] in [xlib.FocusIn, xlib.FocusOut]: # we do not keep track of multiple XICs, just reset xic = xlib.Xutf8ResetIC(self._kbd_replay_xic) if xic is not None: xlib.XFree(xic) return elif ev.type in [xlib.KeyPress, xlib.KeyRelease]: # fake keyboard event data for XFilterEvent ev.xkey.send_event = False ev.xkey.window = self.replay_win # pass _all_ events to XFilterEvent filtered = bool(xlib.XFilterEvent(ev, 0)) if ev.type == xlib.KeyRelease and \ phantom_release(self.replay_dpy, ev.xkey): return if ev.type not in [xlib.KeyPress, xlib.KeyRelease]: return # generate new keyboard event data = KeyData() data.filtered = filtered data.pressed = (ev.type == xlib.KeyPress) data.repeated = (ev.type == self._kbd_last_ev.type and \ ev.xkey.state == self._kbd_last_ev.xkey.state and \ ev.xkey.keycode == self._kbd_last_ev.xkey.keycode) data.mods_mask = ev.xkey.state self._event_modifiers(ev.xkey, data) if not data.filtered and data.pressed and self.kbd_translate: self._event_keypress(ev.xkey, data) else: self._event_lookup(ev.xkey, data) self._event_processed(data) self._kbd_last_ev = ev def _btn_process(self, ev): if ev.type in [xlib.ButtonPress, xlib.ButtonRelease]: data = ButtonData(ev.xbutton.button, ev.type) glib.idle_add(self._event_callback, data) def run(self): # control connection self.control_dpy = xlib.XOpenDisplay(None) xlib.XSynchronize(self.control_dpy, True) # unmapped replay window self.replay_dpy = xlib.XOpenDisplay(None) self.custom_atom = xlib.XInternAtom(self.replay_dpy, b"SCREENKEY", False) replay_fd = xlib.XConnectionNumber(self.replay_dpy) self.replay_win = create_replay_window(self.replay_dpy) # bail during initialization errors try: if self.input_types & InputType.keyboard: self._kbd_init() except Exception as e: self.error = e xlib.XCloseDisplay(self.control_dpy) xlib.XDestroyWindow(self.replay_dpy, self.replay_win) xlib.XCloseDisplay(self.replay_dpy) # cheap wakeup() equivalent for compatibility glib.idle_add(self._event_callback, None) self.stopped = True self.lock.release() return # initialize recording context ev_ranges = [] dev_ranges = [] if self.input_types & InputType.keyboard: ev_ranges.append([xlib.FocusIn, xlib.FocusOut]) dev_ranges.append([xlib.KeyPress, xlib.KeyRelease]) if self.input_types & InputType.button: dev_ranges.append([xlib.ButtonPress, xlib.ButtonRelease]) if self.input_types & InputType.movement: dev_ranges.append([xlib.MotionNotify, xlib.MotionNotify]) self.record_ctx = record_context(self.control_dpy, ev_ranges, dev_ranges); record_dpy = xlib.XOpenDisplay(None) record_fd = xlib.XConnectionNumber(record_dpy) # we need to keep the record_ref alive(!) record_ref = record_enable(record_dpy, self.record_ctx, self._event_received) # event loop self.lock.release() while True: with self.lock: if self.stopped: break r_fd = [] if xlib.XPending(record_dpy): r_fd.append(record_fd) if xlib.XPending(self.replay_dpy): r_fd.append(replay_fd) if not r_fd: r_fd, _, _ = select.select([record_fd, replay_fd], [], []) if not r_fd: break if record_fd in r_fd: xlib.XRecordProcessReplies(record_dpy) xlib.XFlush(self.replay_dpy) if replay_fd in r_fd: ev = xlib.XEvent() xlib.XNextEvent(self.replay_dpy, xlib.byref(ev)) if self.input_types & InputType.keyboard: self._kbd_process(ev) if self.input_types & InputType.button: self._btn_process(ev) # finalize self.lock.acquire() xlib.XRecordFreeContext(self.control_dpy, self.record_ctx) xlib.XCloseDisplay(self.control_dpy) xlib.XCloseDisplay(record_dpy) del record_ref if self.input_types & InputType.keyboard: self._kbd_del() xlib.XDestroyWindow(self.replay_dpy, self.replay_win) xlib.XCloseDisplay(self.replay_dpy) self.stopped = True self.lock.release() if __name__ == '__main__': def callback(data): values = {} for k in dir(data): if k[0] == '_': continue values[k] = getattr(data, k) print(values) kl = InputListener(callback) try: # keep running only while the listener is alive kl.start() while kl.is_alive(): glib.main_context_default().iteration() except KeyboardInterrupt: pass # check if the thread terminated unexpectedly if kl.is_alive(): kl.stop() kl.join() elif kl.error: print("initialization error: {}".format(kl.error)) if '__traceback__' in dir(kl.error): import traceback traceback.print_tb(kl.error.__traceback__) exit(1) screenkey-v1.5/Screenkey/keysyms.py000066400000000000000000002361251415444532700175650ustar00rootroot00000000000000# https://www.cl.cam.ac.uk/~mgk25/ucs/keysyms.txt # Mapping of X11 keysyms to ISO 10646 / Unicode # # The "X11 Window System Protocol" standard (Release 6.4) defines in # Appendix A the keysym codes. These 29-bit integer values identify # characters or functions associated with each key (e.g., via the # visible engraving) of a keyboard layout. In addition, mnemonic macro # names are provided for the keysyms in the C header file # . These are compiled (by xc/lib/X11/util/ # makekeys.c) into a hash table that can be accessed with X11 library # functions such as XStringToKeysym() and XKeysymToString(). # # The creation of the keysym codes predates ISO 10646 / Unicode, but # they represent a similar attempt to merge several existing coded # character sets (mostly early drafts of ISO 8859, as well as some -- # long since forgotten -- DEC font encodings). X.Org and XFree86 have # agreed that for any future extension of the keysyms with characters # already found in ISO 10646 / Unicode, the following algorithm will # be used. The new keysym code position will simply be the character's # Unicode number plus 0x01000000. The keysym codes in the range # 0x01000100 0x0110ffff are now reserved to represent Unicode # characters in the range U0100 to U10FFFF. (Note that the ISO 8859-1 # characters that make up Unicode positions below U0100 are excluded # from this rule, as they are already covered by the keysyms of the # same value.) # # While most newer Unicode-based X11 clients do already accept # Unicode-mapped keysyms in the range 0x01000100 to 0x0110ffff, it # will remain necessary for clients -- in the interest of # compatibility with existing servers -- to also understand the # existing keysym values. Clients can use the table below to map the # pre-Unicode keysym values (0x0100 to 0x20ff) to the corresponding # Unicode characters for further processing. # # The following fields are used in this mapping table: # # 1 The hexadecimal X11 keysym number (as defined in Appendix A of # the X11 protocol specification and as listed in ) # # 2 The corresponding Unicode position # (U0000 means that there is no equivalent Unicode character) # # 3 Status of this keysym and its Unicode mapping # # . regular -- This is a regular well-established keysym with # a straightforward Unicode equivalent (e.g., any keysym # derived from ISO 8859). There can be at most one regular # keysym associated with each Unicode character. # # d duplicate -- This keysym has the same Unicode mapping as # another one with status 'regular'. It represents a case # where keysyms distinguish between several characters that # Unicode has unified into a single one (examples are # several APL symbols) # # o obsolete -- While it may be possible to find a Unicode of # similar name, the exact semantics of this keysym are # unclear, because the font or character set from which it # came has never been widely used. Examples are various # symbols from the DEC Publishing character set, which may # have been used in a special font shipped with the # DECwrite product. Where no similar Unicode character # can be identified, U0000 is used in column 2. # # f function -- While it may be possible to find a Unicode # of similar name, this keysym differs semantically # substantially from the corresponding Unicode character, # because it describes a particular function key or will # first have to be processed by an input method that will # translate it into a proper stream of Unicode characters. # # r remove -- This is a bogus keysym that was added in error, # is not used in any known keyboard layout, and should be # removed from both and the standard. # # u unicode-remap -- This keysym was added rather recently to # the of XFree86, but into a number range # reserved for future extensions of the standard by # X.Org. It is not widely used at present, but its name # appears to be sufficiently useful and it should therefore # be directly mapped to Unicode in the 0x1xxxxxx range in # future versions of . This way, the macro # name will be preserved, but the standard will not have to # be extended. # # Recommendations for using the keysym status: # # - All keysyms with status regular, duplicate, obsolete and # function should be listed in Appendix A of the X11 protocol # spec. # # - All keysyms except for those with status remove should be # listed in . # # - Keysyms with status duplicate, obsolete, and remove should # not be used in future keyboard layouts, as there are other # keysyms with status regular, function and unicode-remap # that give access to the same Unicode characters. # # - Keysym to Unicode conversion tables in clients should include # all mappings except those with status function and those # with U0000. # # # comment marker # # 4 the name of the X11 keysym macro without the leading XK_, # as defined in # # The last columns may be followed by comments copied from . # A keysym may be listed several times, if there are several macro names # associated with it in . # # Author: Markus Kuhn # Date: 2004-08-08 # # This table evolved out of an earlier one by Richard Verhoeven, TU Eindhoven. KEYSYMS = { # We begin with the original keysyms found in X11R6.4 0x0020: ['\u0020', '.'], # space 0x0021: ['\u0021', '.'], # exclam 0x0022: ['\u0022', '.'], # quotedbl 0x0023: ['\u0023', '.'], # numbersign 0x0024: ['\u0024', '.'], # dollar 0x0025: ['\u0025', '.'], # percent 0x0026: ['\u0026', '.'], # ampersand 0x0027: ['\u0027', '.'], # apostrophe 0x0027: ['\u0027', '.'], # quoteright /* deprecated */ 0x0028: ['\u0028', '.'], # parenleft 0x0029: ['\u0029', '.'], # parenright 0x002a: ['\u002a', '.'], # asterisk 0x002b: ['\u002b', '.'], # plus 0x002c: ['\u002c', '.'], # comma 0x002d: ['\u002d', '.'], # minus 0x002e: ['\u002e', '.'], # period 0x002f: ['\u002f', '.'], # slash 0x0030: ['\u0030', '.'], # 0 0x0031: ['\u0031', '.'], # 1 0x0032: ['\u0032', '.'], # 2 0x0033: ['\u0033', '.'], # 3 0x0034: ['\u0034', '.'], # 4 0x0035: ['\u0035', '.'], # 5 0x0036: ['\u0036', '.'], # 6 0x0037: ['\u0037', '.'], # 7 0x0038: ['\u0038', '.'], # 8 0x0039: ['\u0039', '.'], # 9 0x003a: ['\u003a', '.'], # colon 0x003b: ['\u003b', '.'], # semicolon 0x003c: ['\u003c', '.'], # less 0x003d: ['\u003d', '.'], # equal 0x003e: ['\u003e', '.'], # greater 0x003f: ['\u003f', '.'], # question 0x0040: ['\u0040', '.'], # at 0x0041: ['\u0041', '.'], # A 0x0042: ['\u0042', '.'], # B 0x0043: ['\u0043', '.'], # C 0x0044: ['\u0044', '.'], # D 0x0045: ['\u0045', '.'], # E 0x0046: ['\u0046', '.'], # F 0x0047: ['\u0047', '.'], # G 0x0048: ['\u0048', '.'], # H 0x0049: ['\u0049', '.'], # I 0x004a: ['\u004a', '.'], # J 0x004b: ['\u004b', '.'], # K 0x004c: ['\u004c', '.'], # L 0x004d: ['\u004d', '.'], # M 0x004e: ['\u004e', '.'], # N 0x004f: ['\u004f', '.'], # O 0x0050: ['\u0050', '.'], # P 0x0051: ['\u0051', '.'], # Q 0x0052: ['\u0052', '.'], # R 0x0053: ['\u0053', '.'], # S 0x0054: ['\u0054', '.'], # T 0x0055: ['\u0055', '.'], # U 0x0056: ['\u0056', '.'], # V 0x0057: ['\u0057', '.'], # W 0x0058: ['\u0058', '.'], # X 0x0059: ['\u0059', '.'], # Y 0x005a: ['\u005a', '.'], # Z 0x005b: ['\u005b', '.'], # bracketleft 0x005c: ['\u005c', '.'], # backslash 0x005d: ['\u005d', '.'], # bracketright 0x005e: ['\u005e', '.'], # asciicircum 0x005f: ['\u005f', '.'], # underscore 0x0060: ['\u0060', '.'], # grave 0x0060: ['\u0060', '.'], # quoteleft /* deprecated */ 0x0061: ['\u0061', '.'], # a 0x0062: ['\u0062', '.'], # b 0x0063: ['\u0063', '.'], # c 0x0064: ['\u0064', '.'], # d 0x0065: ['\u0065', '.'], # e 0x0066: ['\u0066', '.'], # f 0x0067: ['\u0067', '.'], # g 0x0068: ['\u0068', '.'], # h 0x0069: ['\u0069', '.'], # i 0x006a: ['\u006a', '.'], # j 0x006b: ['\u006b', '.'], # k 0x006c: ['\u006c', '.'], # l 0x006d: ['\u006d', '.'], # m 0x006e: ['\u006e', '.'], # n 0x006f: ['\u006f', '.'], # o 0x0070: ['\u0070', '.'], # p 0x0071: ['\u0071', '.'], # q 0x0072: ['\u0072', '.'], # r 0x0073: ['\u0073', '.'], # s 0x0074: ['\u0074', '.'], # t 0x0075: ['\u0075', '.'], # u 0x0076: ['\u0076', '.'], # v 0x0077: ['\u0077', '.'], # w 0x0078: ['\u0078', '.'], # x 0x0079: ['\u0079', '.'], # y 0x007a: ['\u007a', '.'], # z 0x007b: ['\u007b', '.'], # braceleft 0x007c: ['\u007c', '.'], # bar 0x007d: ['\u007d', '.'], # braceright 0x007e: ['\u007e', '.'], # asciitilde 0x00a0: ['\u00a0', '.'], # nobreakspace 0x00a1: ['\u00a1', '.'], # exclamdown 0x00a2: ['\u00a2', '.'], # cent 0x00a3: ['\u00a3', '.'], # sterling 0x00a4: ['\u00a4', '.'], # currency 0x00a5: ['\u00a5', '.'], # yen 0x00a6: ['\u00a6', '.'], # brokenbar 0x00a7: ['\u00a7', '.'], # section 0x00a8: ['\u00a8', '.'], # diaeresis 0x00a9: ['\u00a9', '.'], # copyright 0x00aa: ['\u00aa', '.'], # ordfeminine 0x00ab: ['\u00ab', '.'], # guillemotleft /* left angle quotation mark */ 0x00ac: ['\u00ac', '.'], # notsign 0x00ad: ['\u00ad', '.'], # hyphen 0x00ae: ['\u00ae', '.'], # registered 0x00af: ['\u00af', '.'], # macron 0x00b0: ['\u00b0', '.'], # degree 0x00b1: ['\u00b1', '.'], # plusminus 0x00b2: ['\u00b2', '.'], # twosuperior 0x00b3: ['\u00b3', '.'], # threesuperior 0x00b4: ['\u00b4', '.'], # acute 0x00b5: ['\u00b5', '.'], # mu 0x00b6: ['\u00b6', '.'], # paragraph 0x00b7: ['\u00b7', '.'], # periodcentered 0x00b8: ['\u00b8', '.'], # cedilla 0x00b9: ['\u00b9', '.'], # onesuperior 0x00ba: ['\u00ba', '.'], # masculine 0x00bb: ['\u00bb', '.'], # guillemotright /* right angle quotation mark */ 0x00bc: ['\u00bc', '.'], # onequarter 0x00bd: ['\u00bd', '.'], # onehalf 0x00be: ['\u00be', '.'], # threequarters 0x00bf: ['\u00bf', '.'], # questiondown 0x00c0: ['\u00c0', '.'], # Agrave 0x00c1: ['\u00c1', '.'], # Aacute 0x00c2: ['\u00c2', '.'], # Acircumflex 0x00c3: ['\u00c3', '.'], # Atilde 0x00c4: ['\u00c4', '.'], # Adiaeresis 0x00c5: ['\u00c5', '.'], # Aring 0x00c6: ['\u00c6', '.'], # AE 0x00c7: ['\u00c7', '.'], # Ccedilla 0x00c8: ['\u00c8', '.'], # Egrave 0x00c9: ['\u00c9', '.'], # Eacute 0x00ca: ['\u00ca', '.'], # Ecircumflex 0x00cb: ['\u00cb', '.'], # Ediaeresis 0x00cc: ['\u00cc', '.'], # Igrave 0x00cd: ['\u00cd', '.'], # Iacute 0x00ce: ['\u00ce', '.'], # Icircumflex 0x00cf: ['\u00cf', '.'], # Idiaeresis 0x00d0: ['\u00d0', '.'], # ETH 0x00d0: ['\u00d0', '.'], # Eth /* deprecated */ 0x00d1: ['\u00d1', '.'], # Ntilde 0x00d2: ['\u00d2', '.'], # Ograve 0x00d3: ['\u00d3', '.'], # Oacute 0x00d4: ['\u00d4', '.'], # Ocircumflex 0x00d5: ['\u00d5', '.'], # Otilde 0x00d6: ['\u00d6', '.'], # Odiaeresis 0x00d7: ['\u00d7', '.'], # multiply 0x00d8: ['\u00d8', '.'], # Ooblique 0x00d9: ['\u00d9', '.'], # Ugrave 0x00da: ['\u00da', '.'], # Uacute 0x00db: ['\u00db', '.'], # Ucircumflex 0x00dc: ['\u00dc', '.'], # Udiaeresis 0x00dd: ['\u00dd', '.'], # Yacute 0x00de: ['\u00de', '.'], # THORN 0x00de: ['\u00de', '.'], # Thorn /* deprecated */ 0x00df: ['\u00df', '.'], # ssharp 0x00e0: ['\u00e0', '.'], # agrave 0x00e1: ['\u00e1', '.'], # aacute 0x00e2: ['\u00e2', '.'], # acircumflex 0x00e3: ['\u00e3', '.'], # atilde 0x00e4: ['\u00e4', '.'], # adiaeresis 0x00e5: ['\u00e5', '.'], # aring 0x00e6: ['\u00e6', '.'], # ae 0x00e7: ['\u00e7', '.'], # ccedilla 0x00e8: ['\u00e8', '.'], # egrave 0x00e9: ['\u00e9', '.'], # eacute 0x00ea: ['\u00ea', '.'], # ecircumflex 0x00eb: ['\u00eb', '.'], # ediaeresis 0x00ec: ['\u00ec', '.'], # igrave 0x00ed: ['\u00ed', '.'], # iacute 0x00ee: ['\u00ee', '.'], # icircumflex 0x00ef: ['\u00ef', '.'], # idiaeresis 0x00f0: ['\u00f0', '.'], # eth 0x00f1: ['\u00f1', '.'], # ntilde 0x00f2: ['\u00f2', '.'], # ograve 0x00f3: ['\u00f3', '.'], # oacute 0x00f4: ['\u00f4', '.'], # ocircumflex 0x00f5: ['\u00f5', '.'], # otilde 0x00f6: ['\u00f6', '.'], # odiaeresis 0x00f7: ['\u00f7', '.'], # division 0x00f8: ['\u00f8', '.'], # oslash 0x00f9: ['\u00f9', '.'], # ugrave 0x00fa: ['\u00fa', '.'], # uacute 0x00fb: ['\u00fb', '.'], # ucircumflex 0x00fc: ['\u00fc', '.'], # udiaeresis 0x00fd: ['\u00fd', '.'], # yacute 0x00fe: ['\u00fe', '.'], # thorn 0x00ff: ['\u00ff', '.'], # ydiaeresis 0x01a1: ['\u0104', '.'], # Aogonek 0x01a2: ['\u02d8', '.'], # breve 0x01a3: ['\u0141', '.'], # Lstroke 0x01a5: ['\u013d', '.'], # Lcaron 0x01a6: ['\u015a', '.'], # Sacute 0x01a9: ['\u0160', '.'], # Scaron 0x01aa: ['\u015e', '.'], # Scedilla 0x01ab: ['\u0164', '.'], # Tcaron 0x01ac: ['\u0179', '.'], # Zacute 0x01ae: ['\u017d', '.'], # Zcaron 0x01af: ['\u017b', '.'], # Zabovedot 0x01b1: ['\u0105', '.'], # aogonek 0x01b2: ['\u02db', '.'], # ogonek 0x01b3: ['\u0142', '.'], # lstroke 0x01b5: ['\u013e', '.'], # lcaron 0x01b6: ['\u015b', '.'], # sacute 0x01b7: ['\u02c7', '.'], # caron 0x01b9: ['\u0161', '.'], # scaron 0x01ba: ['\u015f', '.'], # scedilla 0x01bb: ['\u0165', '.'], # tcaron 0x01bc: ['\u017a', '.'], # zacute 0x01bd: ['\u02dd', '.'], # doubleacute 0x01be: ['\u017e', '.'], # zcaron 0x01bf: ['\u017c', '.'], # zabovedot 0x01c0: ['\u0154', '.'], # Racute 0x01c3: ['\u0102', '.'], # Abreve 0x01c5: ['\u0139', '.'], # Lacute 0x01c6: ['\u0106', '.'], # Cacute 0x01c8: ['\u010c', '.'], # Ccaron 0x01ca: ['\u0118', '.'], # Eogonek 0x01cc: ['\u011a', '.'], # Ecaron 0x01cf: ['\u010e', '.'], # Dcaron 0x01d0: ['\u0110', '.'], # Dstroke 0x01d1: ['\u0143', '.'], # Nacute 0x01d2: ['\u0147', '.'], # Ncaron 0x01d5: ['\u0150', '.'], # Odoubleacute 0x01d8: ['\u0158', '.'], # Rcaron 0x01d9: ['\u016e', '.'], # Uring 0x01db: ['\u0170', '.'], # Udoubleacute 0x01de: ['\u0162', '.'], # Tcedilla 0x01e0: ['\u0155', '.'], # racute 0x01e3: ['\u0103', '.'], # abreve 0x01e5: ['\u013a', '.'], # lacute 0x01e6: ['\u0107', '.'], # cacute 0x01e8: ['\u010d', '.'], # ccaron 0x01ea: ['\u0119', '.'], # eogonek 0x01ec: ['\u011b', '.'], # ecaron 0x01ef: ['\u010f', '.'], # dcaron 0x01f0: ['\u0111', '.'], # dstroke 0x01f1: ['\u0144', '.'], # nacute 0x01f2: ['\u0148', '.'], # ncaron 0x01f5: ['\u0151', '.'], # odoubleacute 0x01f8: ['\u0159', '.'], # rcaron 0x01f9: ['\u016f', '.'], # uring 0x01fb: ['\u0171', '.'], # udoubleacute 0x01fe: ['\u0163', '.'], # tcedilla 0x01ff: ['\u02d9', '.'], # abovedot 0x02a1: ['\u0126', '.'], # Hstroke 0x02a6: ['\u0124', '.'], # Hcircumflex 0x02a9: ['\u0130', '.'], # Iabovedot 0x02ab: ['\u011e', '.'], # Gbreve 0x02ac: ['\u0134', '.'], # Jcircumflex 0x02b1: ['\u0127', '.'], # hstroke 0x02b6: ['\u0125', '.'], # hcircumflex 0x02b9: ['\u0131', '.'], # idotless 0x02bb: ['\u011f', '.'], # gbreve 0x02bc: ['\u0135', '.'], # jcircumflex 0x02c5: ['\u010a', '.'], # Cabovedot 0x02c6: ['\u0108', '.'], # Ccircumflex 0x02d5: ['\u0120', '.'], # Gabovedot 0x02d8: ['\u011c', '.'], # Gcircumflex 0x02dd: ['\u016c', '.'], # Ubreve 0x02de: ['\u015c', '.'], # Scircumflex 0x02e5: ['\u010b', '.'], # cabovedot 0x02e6: ['\u0109', '.'], # ccircumflex 0x02f5: ['\u0121', '.'], # gabovedot 0x02f8: ['\u011d', '.'], # gcircumflex 0x02fd: ['\u016d', '.'], # ubreve 0x02fe: ['\u015d', '.'], # scircumflex 0x03a2: ['\u0138', '.'], # kra 0x03a3: ['\u0156', '.'], # Rcedilla 0x03a5: ['\u0128', '.'], # Itilde 0x03a6: ['\u013b', '.'], # Lcedilla 0x03aa: ['\u0112', '.'], # Emacron 0x03ab: ['\u0122', '.'], # Gcedilla 0x03ac: ['\u0166', '.'], # Tslash 0x03b3: ['\u0157', '.'], # rcedilla 0x03b5: ['\u0129', '.'], # itilde 0x03b6: ['\u013c', '.'], # lcedilla 0x03ba: ['\u0113', '.'], # emacron 0x03bb: ['\u0123', '.'], # gcedilla 0x03bc: ['\u0167', '.'], # tslash 0x03bd: ['\u014a', '.'], # ENG 0x03bf: ['\u014b', '.'], # eng 0x03c0: ['\u0100', '.'], # Amacron 0x03c7: ['\u012e', '.'], # Iogonek 0x03cc: ['\u0116', '.'], # Eabovedot 0x03cf: ['\u012a', '.'], # Imacron 0x03d1: ['\u0145', '.'], # Ncedilla 0x03d2: ['\u014c', '.'], # Omacron 0x03d3: ['\u0136', '.'], # Kcedilla 0x03d9: ['\u0172', '.'], # Uogonek 0x03dd: ['\u0168', '.'], # Utilde 0x03de: ['\u016a', '.'], # Umacron 0x03e0: ['\u0101', '.'], # amacron 0x03e7: ['\u012f', '.'], # iogonek 0x03ec: ['\u0117', '.'], # eabovedot 0x03ef: ['\u012b', '.'], # imacron 0x03f1: ['\u0146', '.'], # ncedilla 0x03f2: ['\u014d', '.'], # omacron 0x03f3: ['\u0137', '.'], # kcedilla 0x03f9: ['\u0173', '.'], # uogonek 0x03fd: ['\u0169', '.'], # utilde 0x03fe: ['\u016b', '.'], # umacron 0x047e: ['\u203e', '.'], # overline 0x04a1: ['\u3002', '.'], # kana_fullstop 0x04a2: ['\u300c', '.'], # kana_openingbracket 0x04a3: ['\u300d', '.'], # kana_closingbracket 0x04a4: ['\u3001', '.'], # kana_comma 0x04a5: ['\u30fb', '.'], # kana_conjunctive 0x04a6: ['\u30f2', '.'], # kana_WO 0x04a7: ['\u30a1', '.'], # kana_a 0x04a8: ['\u30a3', '.'], # kana_i 0x04a9: ['\u30a5', '.'], # kana_u 0x04aa: ['\u30a7', '.'], # kana_e 0x04ab: ['\u30a9', '.'], # kana_o 0x04ac: ['\u30e3', '.'], # kana_ya 0x04ad: ['\u30e5', '.'], # kana_yu 0x04ae: ['\u30e7', '.'], # kana_yo 0x04af: ['\u30c3', '.'], # kana_tsu 0x04b0: ['\u30fc', '.'], # prolongedsound 0x04b1: ['\u30a2', '.'], # kana_A 0x04b2: ['\u30a4', '.'], # kana_I 0x04b3: ['\u30a6', '.'], # kana_U 0x04b4: ['\u30a8', '.'], # kana_E 0x04b5: ['\u30aa', '.'], # kana_O 0x04b6: ['\u30ab', '.'], # kana_KA 0x04b7: ['\u30ad', '.'], # kana_KI 0x04b8: ['\u30af', '.'], # kana_KU 0x04b9: ['\u30b1', '.'], # kana_KE 0x04ba: ['\u30b3', '.'], # kana_KO 0x04bb: ['\u30b5', '.'], # kana_SA 0x04bc: ['\u30b7', '.'], # kana_SHI 0x04bd: ['\u30b9', '.'], # kana_SU 0x04be: ['\u30bb', '.'], # kana_SE 0x04bf: ['\u30bd', '.'], # kana_SO 0x04c0: ['\u30bf', '.'], # kana_TA 0x04c1: ['\u30c1', '.'], # kana_CHI 0x04c2: ['\u30c4', '.'], # kana_TSU 0x04c3: ['\u30c6', '.'], # kana_TE 0x04c4: ['\u30c8', '.'], # kana_TO 0x04c5: ['\u30ca', '.'], # kana_NA 0x04c6: ['\u30cb', '.'], # kana_NI 0x04c7: ['\u30cc', '.'], # kana_NU 0x04c8: ['\u30cd', '.'], # kana_NE 0x04c9: ['\u30ce', '.'], # kana_NO 0x04ca: ['\u30cf', '.'], # kana_HA 0x04cb: ['\u30d2', '.'], # kana_HI 0x04cc: ['\u30d5', '.'], # kana_FU 0x04cd: ['\u30d8', '.'], # kana_HE 0x04ce: ['\u30db', '.'], # kana_HO 0x04cf: ['\u30de', '.'], # kana_MA 0x04d0: ['\u30df', '.'], # kana_MI 0x04d1: ['\u30e0', '.'], # kana_MU 0x04d2: ['\u30e1', '.'], # kana_ME 0x04d3: ['\u30e2', '.'], # kana_MO 0x04d4: ['\u30e4', '.'], # kana_YA 0x04d5: ['\u30e6', '.'], # kana_YU 0x04d6: ['\u30e8', '.'], # kana_YO 0x04d7: ['\u30e9', '.'], # kana_RA 0x04d8: ['\u30ea', '.'], # kana_RI 0x04d9: ['\u30eb', '.'], # kana_RU 0x04da: ['\u30ec', '.'], # kana_RE 0x04db: ['\u30ed', '.'], # kana_RO 0x04dc: ['\u30ef', '.'], # kana_WA 0x04dd: ['\u30f3', '.'], # kana_N 0x04de: ['\u309b', '.'], # voicedsound 0x04df: ['\u309c', '.'], # semivoicedsound 0x05ac: ['\u060c', '.'], # Arabic_comma 0x05bb: ['\u061b', '.'], # Arabic_semicolon 0x05bf: ['\u061f', '.'], # Arabic_question_mark 0x05c1: ['\u0621', '.'], # Arabic_hamza 0x05c2: ['\u0622', '.'], # Arabic_maddaonalef 0x05c3: ['\u0623', '.'], # Arabic_hamzaonalef 0x05c4: ['\u0624', '.'], # Arabic_hamzaonwaw 0x05c5: ['\u0625', '.'], # Arabic_hamzaunderalef 0x05c6: ['\u0626', '.'], # Arabic_hamzaonyeh 0x05c7: ['\u0627', '.'], # Arabic_alef 0x05c8: ['\u0628', '.'], # Arabic_beh 0x05c9: ['\u0629', '.'], # Arabic_tehmarbuta 0x05ca: ['\u062a', '.'], # Arabic_teh 0x05cb: ['\u062b', '.'], # Arabic_theh 0x05cc: ['\u062c', '.'], # Arabic_jeem 0x05cd: ['\u062d', '.'], # Arabic_hah 0x05ce: ['\u062e', '.'], # Arabic_khah 0x05cf: ['\u062f', '.'], # Arabic_dal 0x05d0: ['\u0630', '.'], # Arabic_thal 0x05d1: ['\u0631', '.'], # Arabic_ra 0x05d2: ['\u0632', '.'], # Arabic_zain 0x05d3: ['\u0633', '.'], # Arabic_seen 0x05d4: ['\u0634', '.'], # Arabic_sheen 0x05d5: ['\u0635', '.'], # Arabic_sad 0x05d6: ['\u0636', '.'], # Arabic_dad 0x05d7: ['\u0637', '.'], # Arabic_tah 0x05d8: ['\u0638', '.'], # Arabic_zah 0x05d9: ['\u0639', '.'], # Arabic_ain 0x05da: ['\u063a', '.'], # Arabic_ghain 0x05e0: ['\u0640', '.'], # Arabic_tatweel 0x05e1: ['\u0641', '.'], # Arabic_feh 0x05e2: ['\u0642', '.'], # Arabic_qaf 0x05e3: ['\u0643', '.'], # Arabic_kaf 0x05e4: ['\u0644', '.'], # Arabic_lam 0x05e5: ['\u0645', '.'], # Arabic_meem 0x05e6: ['\u0646', '.'], # Arabic_noon 0x05e7: ['\u0647', '.'], # Arabic_ha 0x05e8: ['\u0648', '.'], # Arabic_waw 0x05e9: ['\u0649', '.'], # Arabic_alefmaksura 0x05ea: ['\u064a', '.'], # Arabic_yeh 0x05eb: ['\u064b', '.'], # Arabic_fathatan 0x05ec: ['\u064c', '.'], # Arabic_dammatan 0x05ed: ['\u064d', '.'], # Arabic_kasratan 0x05ee: ['\u064e', '.'], # Arabic_fatha 0x05ef: ['\u064f', '.'], # Arabic_damma 0x05f0: ['\u0650', '.'], # Arabic_kasra 0x05f1: ['\u0651', '.'], # Arabic_shadda 0x05f2: ['\u0652', '.'], # Arabic_sukun 0x06a1: ['\u0452', '.'], # Serbian_dje 0x06a2: ['\u0453', '.'], # Macedonia_gje 0x06a3: ['\u0451', '.'], # Cyrillic_io 0x06a4: ['\u0454', '.'], # Ukrainian_ie 0x06a5: ['\u0455', '.'], # Macedonia_dse 0x06a6: ['\u0456', '.'], # Ukrainian_i 0x06a7: ['\u0457', '.'], # Ukrainian_yi 0x06a8: ['\u0458', '.'], # Cyrillic_je 0x06a9: ['\u0459', '.'], # Cyrillic_lje 0x06aa: ['\u045a', '.'], # Cyrillic_nje 0x06ab: ['\u045b', '.'], # Serbian_tshe 0x06ac: ['\u045c', '.'], # Macedonia_kje 0x06ae: ['\u045e', '.'], # Byelorussian_shortu 0x06af: ['\u045f', '.'], # Cyrillic_dzhe 0x06b0: ['\u2116', '.'], # numerosign 0x06b1: ['\u0402', '.'], # Serbian_DJE 0x06b2: ['\u0403', '.'], # Macedonia_GJE 0x06b3: ['\u0401', '.'], # Cyrillic_IO 0x06b4: ['\u0404', '.'], # Ukrainian_IE 0x06b5: ['\u0405', '.'], # Macedonia_DSE 0x06b6: ['\u0406', '.'], # Ukrainian_I 0x06b7: ['\u0407', '.'], # Ukrainian_YI 0x06b8: ['\u0408', '.'], # Cyrillic_JE 0x06b9: ['\u0409', '.'], # Cyrillic_LJE 0x06ba: ['\u040a', '.'], # Cyrillic_NJE 0x06bb: ['\u040b', '.'], # Serbian_TSHE 0x06bc: ['\u040c', '.'], # Macedonia_KJE 0x06be: ['\u040e', '.'], # Byelorussian_SHORTU 0x06bf: ['\u040f', '.'], # Cyrillic_DZHE 0x06c0: ['\u044e', '.'], # Cyrillic_yu 0x06c1: ['\u0430', '.'], # Cyrillic_a 0x06c2: ['\u0431', '.'], # Cyrillic_be 0x06c3: ['\u0446', '.'], # Cyrillic_tse 0x06c4: ['\u0434', '.'], # Cyrillic_de 0x06c5: ['\u0435', '.'], # Cyrillic_ie 0x06c6: ['\u0444', '.'], # Cyrillic_ef 0x06c7: ['\u0433', '.'], # Cyrillic_ghe 0x06c8: ['\u0445', '.'], # Cyrillic_ha 0x06c9: ['\u0438', '.'], # Cyrillic_i 0x06ca: ['\u0439', '.'], # Cyrillic_shorti 0x06cb: ['\u043a', '.'], # Cyrillic_ka 0x06cc: ['\u043b', '.'], # Cyrillic_el 0x06cd: ['\u043c', '.'], # Cyrillic_em 0x06ce: ['\u043d', '.'], # Cyrillic_en 0x06cf: ['\u043e', '.'], # Cyrillic_o 0x06d0: ['\u043f', '.'], # Cyrillic_pe 0x06d1: ['\u044f', '.'], # Cyrillic_ya 0x06d2: ['\u0440', '.'], # Cyrillic_er 0x06d3: ['\u0441', '.'], # Cyrillic_es 0x06d4: ['\u0442', '.'], # Cyrillic_te 0x06d5: ['\u0443', '.'], # Cyrillic_u 0x06d6: ['\u0436', '.'], # Cyrillic_zhe 0x06d7: ['\u0432', '.'], # Cyrillic_ve 0x06d8: ['\u044c', '.'], # Cyrillic_softsign 0x06d9: ['\u044b', '.'], # Cyrillic_yeru 0x06da: ['\u0437', '.'], # Cyrillic_ze 0x06db: ['\u0448', '.'], # Cyrillic_sha 0x06dc: ['\u044d', '.'], # Cyrillic_e 0x06dd: ['\u0449', '.'], # Cyrillic_shcha 0x06de: ['\u0447', '.'], # Cyrillic_che 0x06df: ['\u044a', '.'], # Cyrillic_hardsign 0x06e0: ['\u042e', '.'], # Cyrillic_YU 0x06e1: ['\u0410', '.'], # Cyrillic_A 0x06e2: ['\u0411', '.'], # Cyrillic_BE 0x06e3: ['\u0426', '.'], # Cyrillic_TSE 0x06e4: ['\u0414', '.'], # Cyrillic_DE 0x06e5: ['\u0415', '.'], # Cyrillic_IE 0x06e6: ['\u0424', '.'], # Cyrillic_EF 0x06e7: ['\u0413', '.'], # Cyrillic_GHE 0x06e8: ['\u0425', '.'], # Cyrillic_HA 0x06e9: ['\u0418', '.'], # Cyrillic_I 0x06ea: ['\u0419', '.'], # Cyrillic_SHORTI 0x06eb: ['\u041a', '.'], # Cyrillic_KA 0x06ec: ['\u041b', '.'], # Cyrillic_EL 0x06ed: ['\u041c', '.'], # Cyrillic_EM 0x06ee: ['\u041d', '.'], # Cyrillic_EN 0x06ef: ['\u041e', '.'], # Cyrillic_O 0x06f0: ['\u041f', '.'], # Cyrillic_PE 0x06f1: ['\u042f', '.'], # Cyrillic_YA 0x06f2: ['\u0420', '.'], # Cyrillic_ER 0x06f3: ['\u0421', '.'], # Cyrillic_ES 0x06f4: ['\u0422', '.'], # Cyrillic_TE 0x06f5: ['\u0423', '.'], # Cyrillic_U 0x06f6: ['\u0416', '.'], # Cyrillic_ZHE 0x06f7: ['\u0412', '.'], # Cyrillic_VE 0x06f8: ['\u042c', '.'], # Cyrillic_SOFTSIGN 0x06f9: ['\u042b', '.'], # Cyrillic_YERU 0x06fa: ['\u0417', '.'], # Cyrillic_ZE 0x06fb: ['\u0428', '.'], # Cyrillic_SHA 0x06fc: ['\u042d', '.'], # Cyrillic_E 0x06fd: ['\u0429', '.'], # Cyrillic_SHCHA 0x06fe: ['\u0427', '.'], # Cyrillic_CHE 0x06ff: ['\u042a', '.'], # Cyrillic_HARDSIGN 0x07a1: ['\u0386', '.'], # Greek_ALPHAaccent 0x07a2: ['\u0388', '.'], # Greek_EPSILONaccent 0x07a3: ['\u0389', '.'], # Greek_ETAaccent 0x07a4: ['\u038a', '.'], # Greek_IOTAaccent 0x07a5: ['\u03aa', '.'], # Greek_IOTAdiaeresis 0x07a7: ['\u038c', '.'], # Greek_OMICRONaccent 0x07a8: ['\u038e', '.'], # Greek_UPSILONaccent 0x07a9: ['\u03ab', '.'], # Greek_UPSILONdieresis 0x07ab: ['\u038f', '.'], # Greek_OMEGAaccent 0x07ae: ['\u0385', '.'], # Greek_accentdieresis 0x07af: ['\u2015', '.'], # Greek_horizbar 0x07b1: ['\u03ac', '.'], # Greek_alphaaccent 0x07b2: ['\u03ad', '.'], # Greek_epsilonaccent 0x07b3: ['\u03ae', '.'], # Greek_etaaccent 0x07b4: ['\u03af', '.'], # Greek_iotaaccent 0x07b5: ['\u03ca', '.'], # Greek_iotadieresis 0x07b6: ['\u0390', '.'], # Greek_iotaaccentdieresis 0x07b7: ['\u03cc', '.'], # Greek_omicronaccent 0x07b8: ['\u03cd', '.'], # Greek_upsilonaccent 0x07b9: ['\u03cb', '.'], # Greek_upsilondieresis 0x07ba: ['\u03b0', '.'], # Greek_upsilonaccentdieresis 0x07bb: ['\u03ce', '.'], # Greek_omegaaccent 0x07c1: ['\u0391', '.'], # Greek_ALPHA 0x07c2: ['\u0392', '.'], # Greek_BETA 0x07c3: ['\u0393', '.'], # Greek_GAMMA 0x07c4: ['\u0394', '.'], # Greek_DELTA 0x07c5: ['\u0395', '.'], # Greek_EPSILON 0x07c6: ['\u0396', '.'], # Greek_ZETA 0x07c7: ['\u0397', '.'], # Greek_ETA 0x07c8: ['\u0398', '.'], # Greek_THETA 0x07c9: ['\u0399', '.'], # Greek_IOTA 0x07ca: ['\u039a', '.'], # Greek_KAPPA 0x07cb: ['\u039b', '.'], # Greek_LAMBDA 0x07cb: ['\u039b', '.'], # Greek_LAMDA 0x07cc: ['\u039c', '.'], # Greek_MU 0x07cd: ['\u039d', '.'], # Greek_NU 0x07ce: ['\u039e', '.'], # Greek_XI 0x07cf: ['\u039f', '.'], # Greek_OMICRON 0x07d0: ['\u03a0', '.'], # Greek_PI 0x07d1: ['\u03a1', '.'], # Greek_RHO 0x07d2: ['\u03a3', '.'], # Greek_SIGMA 0x07d4: ['\u03a4', '.'], # Greek_TAU 0x07d5: ['\u03a5', '.'], # Greek_UPSILON 0x07d6: ['\u03a6', '.'], # Greek_PHI 0x07d7: ['\u03a7', '.'], # Greek_CHI 0x07d8: ['\u03a8', '.'], # Greek_PSI 0x07d9: ['\u03a9', '.'], # Greek_OMEGA 0x07e1: ['\u03b1', '.'], # Greek_alpha 0x07e2: ['\u03b2', '.'], # Greek_beta 0x07e3: ['\u03b3', '.'], # Greek_gamma 0x07e4: ['\u03b4', '.'], # Greek_delta 0x07e5: ['\u03b5', '.'], # Greek_epsilon 0x07e6: ['\u03b6', '.'], # Greek_zeta 0x07e7: ['\u03b7', '.'], # Greek_eta 0x07e8: ['\u03b8', '.'], # Greek_theta 0x07e9: ['\u03b9', '.'], # Greek_iota 0x07ea: ['\u03ba', '.'], # Greek_kappa 0x07eb: ['\u03bb', '.'], # Greek_lambda 0x07ec: ['\u03bc', '.'], # Greek_mu 0x07ed: ['\u03bd', '.'], # Greek_nu 0x07ee: ['\u03be', '.'], # Greek_xi 0x07ef: ['\u03bf', '.'], # Greek_omicron 0x07f0: ['\u03c0', '.'], # Greek_pi 0x07f1: ['\u03c1', '.'], # Greek_rho 0x07f2: ['\u03c3', '.'], # Greek_sigma 0x07f3: ['\u03c2', '.'], # Greek_finalsmallsigma 0x07f4: ['\u03c4', '.'], # Greek_tau 0x07f5: ['\u03c5', '.'], # Greek_upsilon 0x07f6: ['\u03c6', '.'], # Greek_phi 0x07f7: ['\u03c7', '.'], # Greek_chi 0x07f8: ['\u03c8', '.'], # Greek_psi 0x07f9: ['\u03c9', '.'], # Greek_omega 0x08a1: ['\u23b7', '.'], # leftradical 0x08a2: ['\u250c', 'd'], # topleftradical 0x08a3: ['\u2500', 'd'], # horizconnector 0x08a4: ['\u2320', '.'], # topintegral 0x08a5: ['\u2321', '.'], # botintegral 0x08a6: ['\u2502', 'd'], # vertconnector 0x08a7: ['\u23a1', '.'], # topleftsqbracket 0x08a8: ['\u23a3', '.'], # botleftsqbracket 0x08a9: ['\u23a4', '.'], # toprightsqbracket 0x08aa: ['\u23a6', '.'], # botrightsqbracket 0x08ab: ['\u239b', '.'], # topleftparens 0x08ac: ['\u239d', '.'], # botleftparens 0x08ad: ['\u239e', '.'], # toprightparens 0x08ae: ['\u23a0', '.'], # botrightparens 0x08af: ['\u23a8', '.'], # leftmiddlecurlybrace 0x08b0: ['\u23ac', '.'], # rightmiddlecurlybrace 0x08b1: [None , 'o'], # topleftsummation 0x08b2: [None , 'o'], # botleftsummation 0x08b3: [None , 'o'], # topvertsummationconnector 0x08b4: [None , 'o'], # botvertsummationconnector 0x08b5: [None , 'o'], # toprightsummation 0x08b6: [None , 'o'], # botrightsummation 0x08b7: [None , 'o'], # rightmiddlesummation 0x08bc: ['\u2264', '.'], # lessthanequal 0x08bd: ['\u2260', '.'], # notequal 0x08be: ['\u2265', '.'], # greaterthanequal 0x08bf: ['\u222b', '.'], # integral 0x08c0: ['\u2234', '.'], # therefore 0x08c1: ['\u221d', '.'], # variation 0x08c2: ['\u221e', '.'], # infinity 0x08c5: ['\u2207', '.'], # nabla 0x08c8: ['\u223c', '.'], # approximate 0x08c9: ['\u2243', '.'], # similarequal 0x08cd: ['\u21d4', '.'], # ifonlyif 0x08ce: ['\u21d2', '.'], # implies 0x08cf: ['\u2261', '.'], # identical 0x08d6: ['\u221a', '.'], # radical 0x08da: ['\u2282', '.'], # includedin 0x08db: ['\u2283', '.'], # includes 0x08dc: ['\u2229', '.'], # intersection 0x08dd: ['\u222a', '.'], # union 0x08de: ['\u2227', '.'], # logicaland 0x08df: ['\u2228', '.'], # logicalor 0x08ef: ['\u2202', '.'], # partialderivative 0x08f6: ['\u0192', '.'], # function 0x08fb: ['\u2190', '.'], # leftarrow 0x08fc: ['\u2191', '.'], # uparrow 0x08fd: ['\u2192', '.'], # rightarrow 0x08fe: ['\u2193', '.'], # downarrow 0x09df: [None , 'o'], # blank 0x09e0: ['\u25c6', '.'], # soliddiamond 0x09e1: ['\u2592', '.'], # checkerboard 0x09e2: ['\u2409', '.'], # ht 0x09e3: ['\u240c', '.'], # ff 0x09e4: ['\u240d', '.'], # cr 0x09e5: ['\u240a', '.'], # lf 0x09e8: ['\u2424', '.'], # nl 0x09e9: ['\u240b', '.'], # vt 0x09ea: ['\u2518', '.'], # lowrightcorner 0x09eb: ['\u2510', '.'], # uprightcorner 0x09ec: ['\u250c', '.'], # upleftcorner 0x09ed: ['\u2514', '.'], # lowleftcorner 0x09ee: ['\u253c', '.'], # crossinglines 0x09ef: ['\u23ba', '.'], # horizlinescan1 0x09f0: ['\u23bb', '.'], # horizlinescan3 0x09f1: ['\u2500', '.'], # horizlinescan5 0x09f2: ['\u23bc', '.'], # horizlinescan7 0x09f3: ['\u23bd', '.'], # horizlinescan9 0x09f4: ['\u251c', '.'], # leftt 0x09f5: ['\u2524', '.'], # rightt 0x09f6: ['\u2534', '.'], # bott 0x09f7: ['\u252c', '.'], # topt 0x09f8: ['\u2502', '.'], # vertbar 0x0aa1: ['\u2003', '.'], # emspace 0x0aa2: ['\u2002', '.'], # enspace 0x0aa3: ['\u2004', '.'], # em3space 0x0aa4: ['\u2005', '.'], # em4space 0x0aa5: ['\u2007', '.'], # digitspace 0x0aa6: ['\u2008', '.'], # punctspace 0x0aa7: ['\u2009', '.'], # thinspace 0x0aa8: ['\u200a', '.'], # hairspace 0x0aa9: ['\u2014', '.'], # emdash 0x0aaa: ['\u2013', '.'], # endash 0x0aac: ['\u2423', 'o'], # signifblank 0x0aae: ['\u2026', '.'], # ellipsis 0x0aaf: ['\u2025', '.'], # doubbaselinedot 0x0ab0: ['\u2153', '.'], # onethird 0x0ab1: ['\u2154', '.'], # twothirds 0x0ab2: ['\u2155', '.'], # onefifth 0x0ab3: ['\u2156', '.'], # twofifths 0x0ab4: ['\u2157', '.'], # threefifths 0x0ab5: ['\u2158', '.'], # fourfifths 0x0ab6: ['\u2159', '.'], # onesixth 0x0ab7: ['\u215a', '.'], # fivesixths 0x0ab8: ['\u2105', '.'], # careof 0x0abb: ['\u2012', '.'], # figdash 0x0abc: ['\u27e8', 'o'], # leftanglebracket 0x0abd: ['\u002e', 'o'], # decimalpoint 0x0abe: ['\u27e9', 'o'], # rightanglebracket 0x0abf: [None , 'o'], # marker 0x0ac3: ['\u215b', '.'], # oneeighth 0x0ac4: ['\u215c', '.'], # threeeighths 0x0ac5: ['\u215d', '.'], # fiveeighths 0x0ac6: ['\u215e', '.'], # seveneighths 0x0ac9: ['\u2122', '.'], # trademark 0x0aca: ['\u2613', 'o'], # signaturemark 0x0acb: [None , 'o'], # trademarkincircle 0x0acc: ['\u25c1', 'o'], # leftopentriangle 0x0acd: ['\u25b7', 'o'], # rightopentriangle 0x0ace: ['\u25cb', 'o'], # emopencircle 0x0acf: ['\u25af', 'o'], # emopenrectangle 0x0ad0: ['\u2018', '.'], # leftsinglequotemark 0x0ad1: ['\u2019', '.'], # rightsinglequotemark 0x0ad2: ['\u201c', '.'], # leftdoublequotemark 0x0ad3: ['\u201d', '.'], # rightdoublequotemark 0x0ad4: ['\u211e', '.'], # prescription 0x0ad6: ['\u2032', '.'], # minutes 0x0ad7: ['\u2033', '.'], # seconds 0x0ad9: ['\u271d', '.'], # latincross 0x0ada: [None , 'o'], # hexagram 0x0adb: ['\u25ac', 'o'], # filledrectbullet 0x0adc: ['\u25c0', 'o'], # filledlefttribullet 0x0add: ['\u25b6', 'o'], # filledrighttribullet 0x0ade: ['\u25cf', 'o'], # emfilledcircle 0x0adf: ['\u25ae', 'o'], # emfilledrect 0x0ae0: ['\u25e6', 'o'], # enopencircbullet 0x0ae1: ['\u25ab', 'o'], # enopensquarebullet 0x0ae2: ['\u25ad', 'o'], # openrectbullet 0x0ae3: ['\u25b3', 'o'], # opentribulletup 0x0ae4: ['\u25bd', 'o'], # opentribulletdown 0x0ae5: ['\u2606', 'o'], # openstar 0x0ae6: ['\u2022', 'o'], # enfilledcircbullet 0x0ae7: ['\u25aa', 'o'], # enfilledsqbullet 0x0ae8: ['\u25b2', 'o'], # filledtribulletup 0x0ae9: ['\u25bc', 'o'], # filledtribulletdown 0x0aea: ['\u261c', 'o'], # leftpointer 0x0aeb: ['\u261e', 'o'], # rightpointer 0x0aec: ['\u2663', '.'], # club 0x0aed: ['\u2666', '.'], # diamond 0x0aee: ['\u2665', '.'], # heart 0x0af0: ['\u2720', '.'], # maltesecross 0x0af1: ['\u2020', '.'], # dagger 0x0af2: ['\u2021', '.'], # doubledagger 0x0af3: ['\u2713', '.'], # checkmark 0x0af4: ['\u2717', '.'], # ballotcross 0x0af5: ['\u266f', '.'], # musicalsharp 0x0af6: ['\u266d', '.'], # musicalflat 0x0af7: ['\u2642', '.'], # malesymbol 0x0af8: ['\u2640', '.'], # femalesymbol 0x0af9: ['\u260e', '.'], # telephone 0x0afa: ['\u2315', '.'], # telephonerecorder 0x0afb: ['\u2117', '.'], # phonographcopyright 0x0afc: ['\u2038', '.'], # caret 0x0afd: ['\u201a', '.'], # singlelowquotemark 0x0afe: ['\u201e', '.'], # doublelowquotemark 0x0aff: [None , 'o'], # cursor 0x0ba3: ['\u003c', 'd'], # leftcaret 0x0ba6: ['\u003e', 'd'], # rightcaret 0x0ba8: ['\u2228', 'd'], # downcaret 0x0ba9: ['\u2227', 'd'], # upcaret 0x0bc0: ['\u00af', 'd'], # overbar 0x0bc2: ['\u22a5', '.'], # downtack 0x0bc3: ['\u2229', 'd'], # upshoe 0x0bc4: ['\u230a', '.'], # downstile 0x0bc6: ['\u005f', 'd'], # underbar 0x0bca: ['\u2218', '.'], # jot 0x0bcc: ['\u2395', '.'], # quad 0x0bce: ['\u22a4', '.'], # uptack 0x0bcf: ['\u25cb', '.'], # circle 0x0bd3: ['\u2308', '.'], # upstile 0x0bd6: ['\u222a', 'd'], # downshoe 0x0bd8: ['\u2283', 'd'], # rightshoe 0x0bda: ['\u2282', 'd'], # leftshoe 0x0bdc: ['\u22a2', '.'], # lefttack 0x0bfc: ['\u22a3', '.'], # righttack 0x0cdf: ['\u2017', '.'], # hebrew_doublelowline 0x0ce0: ['\u05d0', '.'], # hebrew_aleph 0x0ce1: ['\u05d1', '.'], # hebrew_bet 0x0ce1: ['\u05d1', '.'], # hebrew_beth /* deprecated */ 0x0ce2: ['\u05d2', '.'], # hebrew_gimel 0x0ce2: ['\u05d2', '.'], # hebrew_gimmel /* deprecated */ 0x0ce3: ['\u05d3', '.'], # hebrew_dalet 0x0ce3: ['\u05d3', '.'], # hebrew_daleth /* deprecated */ 0x0ce4: ['\u05d4', '.'], # hebrew_he 0x0ce5: ['\u05d5', '.'], # hebrew_waw 0x0ce6: ['\u05d6', '.'], # hebrew_zain 0x0ce6: ['\u05d6', '.'], # hebrew_zayin /* deprecated */ 0x0ce7: ['\u05d7', '.'], # hebrew_chet 0x0ce7: ['\u05d7', '.'], # hebrew_het /* deprecated */ 0x0ce8: ['\u05d8', '.'], # hebrew_tet 0x0ce8: ['\u05d8', '.'], # hebrew_teth /* deprecated */ 0x0ce9: ['\u05d9', '.'], # hebrew_yod 0x0cea: ['\u05da', '.'], # hebrew_finalkaph 0x0ceb: ['\u05db', '.'], # hebrew_kaph 0x0cec: ['\u05dc', '.'], # hebrew_lamed 0x0ced: ['\u05dd', '.'], # hebrew_finalmem 0x0cee: ['\u05de', '.'], # hebrew_mem 0x0cef: ['\u05df', '.'], # hebrew_finalnun 0x0cf0: ['\u05e0', '.'], # hebrew_nun 0x0cf1: ['\u05e1', '.'], # hebrew_samech 0x0cf1: ['\u05e1', '.'], # hebrew_samekh /* deprecated */ 0x0cf2: ['\u05e2', '.'], # hebrew_ayin 0x0cf3: ['\u05e3', '.'], # hebrew_finalpe 0x0cf4: ['\u05e4', '.'], # hebrew_pe 0x0cf5: ['\u05e5', '.'], # hebrew_finalzade 0x0cf5: ['\u05e5', '.'], # hebrew_finalzadi /* deprecated */ 0x0cf6: ['\u05e6', '.'], # hebrew_zade 0x0cf6: ['\u05e6', '.'], # hebrew_zadi /* deprecated */ 0x0cf7: ['\u05e7', '.'], # hebrew_kuf /* deprecated */ 0x0cf7: ['\u05e7', '.'], # hebrew_qoph 0x0cf8: ['\u05e8', '.'], # hebrew_resh 0x0cf9: ['\u05e9', '.'], # hebrew_shin 0x0cfa: ['\u05ea', '.'], # hebrew_taf /* deprecated */ 0x0cfa: ['\u05ea', '.'], # hebrew_taw 0x0da1: ['\u0e01', '.'], # Thai_kokai 0x0da2: ['\u0e02', '.'], # Thai_khokhai 0x0da3: ['\u0e03', '.'], # Thai_khokhuat 0x0da4: ['\u0e04', '.'], # Thai_khokhwai 0x0da5: ['\u0e05', '.'], # Thai_khokhon 0x0da6: ['\u0e06', '.'], # Thai_khorakhang 0x0da7: ['\u0e07', '.'], # Thai_ngongu 0x0da8: ['\u0e08', '.'], # Thai_chochan 0x0da9: ['\u0e09', '.'], # Thai_choching 0x0daa: ['\u0e0a', '.'], # Thai_chochang 0x0dab: ['\u0e0b', '.'], # Thai_soso 0x0dac: ['\u0e0c', '.'], # Thai_chochoe 0x0dad: ['\u0e0d', '.'], # Thai_yoying 0x0dae: ['\u0e0e', '.'], # Thai_dochada 0x0daf: ['\u0e0f', '.'], # Thai_topatak 0x0db0: ['\u0e10', '.'], # Thai_thothan 0x0db1: ['\u0e11', '.'], # Thai_thonangmontho 0x0db2: ['\u0e12', '.'], # Thai_thophuthao 0x0db3: ['\u0e13', '.'], # Thai_nonen 0x0db4: ['\u0e14', '.'], # Thai_dodek 0x0db5: ['\u0e15', '.'], # Thai_totao 0x0db6: ['\u0e16', '.'], # Thai_thothung 0x0db7: ['\u0e17', '.'], # Thai_thothahan 0x0db8: ['\u0e18', '.'], # Thai_thothong 0x0db9: ['\u0e19', '.'], # Thai_nonu 0x0dba: ['\u0e1a', '.'], # Thai_bobaimai 0x0dbb: ['\u0e1b', '.'], # Thai_popla 0x0dbc: ['\u0e1c', '.'], # Thai_phophung 0x0dbd: ['\u0e1d', '.'], # Thai_fofa 0x0dbe: ['\u0e1e', '.'], # Thai_phophan 0x0dbf: ['\u0e1f', '.'], # Thai_fofan 0x0dc0: ['\u0e20', '.'], # Thai_phosamphao 0x0dc1: ['\u0e21', '.'], # Thai_moma 0x0dc2: ['\u0e22', '.'], # Thai_yoyak 0x0dc3: ['\u0e23', '.'], # Thai_rorua 0x0dc4: ['\u0e24', '.'], # Thai_ru 0x0dc5: ['\u0e25', '.'], # Thai_loling 0x0dc6: ['\u0e26', '.'], # Thai_lu 0x0dc7: ['\u0e27', '.'], # Thai_wowaen 0x0dc8: ['\u0e28', '.'], # Thai_sosala 0x0dc9: ['\u0e29', '.'], # Thai_sorusi 0x0dca: ['\u0e2a', '.'], # Thai_sosua 0x0dcb: ['\u0e2b', '.'], # Thai_hohip 0x0dcc: ['\u0e2c', '.'], # Thai_lochula 0x0dcd: ['\u0e2d', '.'], # Thai_oang 0x0dce: ['\u0e2e', '.'], # Thai_honokhuk 0x0dcf: ['\u0e2f', '.'], # Thai_paiyannoi 0x0dd0: ['\u0e30', '.'], # Thai_saraa 0x0dd1: ['\u0e31', '.'], # Thai_maihanakat 0x0dd2: ['\u0e32', '.'], # Thai_saraaa 0x0dd3: ['\u0e33', '.'], # Thai_saraam 0x0dd4: ['\u0e34', '.'], # Thai_sarai 0x0dd5: ['\u0e35', '.'], # Thai_saraii 0x0dd6: ['\u0e36', '.'], # Thai_saraue 0x0dd7: ['\u0e37', '.'], # Thai_sarauee 0x0dd8: ['\u0e38', '.'], # Thai_sarau 0x0dd9: ['\u0e39', '.'], # Thai_sarauu 0x0dda: ['\u0e3a', '.'], # Thai_phinthu 0x0dde: [None , 'o'], # Thai_maihanakat_maitho 0x0ddf: ['\u0e3f', '.'], # Thai_baht 0x0de0: ['\u0e40', '.'], # Thai_sarae 0x0de1: ['\u0e41', '.'], # Thai_saraae 0x0de2: ['\u0e42', '.'], # Thai_sarao 0x0de3: ['\u0e43', '.'], # Thai_saraaimaimuan 0x0de4: ['\u0e44', '.'], # Thai_saraaimaimalai 0x0de5: ['\u0e45', '.'], # Thai_lakkhangyao 0x0de6: ['\u0e46', '.'], # Thai_maiyamok 0x0de7: ['\u0e47', '.'], # Thai_maitaikhu 0x0de8: ['\u0e48', '.'], # Thai_maiek 0x0de9: ['\u0e49', '.'], # Thai_maitho 0x0dea: ['\u0e4a', '.'], # Thai_maitri 0x0deb: ['\u0e4b', '.'], # Thai_maichattawa 0x0dec: ['\u0e4c', '.'], # Thai_thanthakhat 0x0ded: ['\u0e4d', '.'], # Thai_nikhahit 0x0df0: ['\u0e50', '.'], # Thai_leksun 0x0df1: ['\u0e51', '.'], # Thai_leknung 0x0df2: ['\u0e52', '.'], # Thai_leksong 0x0df3: ['\u0e53', '.'], # Thai_leksam 0x0df4: ['\u0e54', '.'], # Thai_leksi 0x0df5: ['\u0e55', '.'], # Thai_lekha 0x0df6: ['\u0e56', '.'], # Thai_lekhok 0x0df7: ['\u0e57', '.'], # Thai_lekchet 0x0df8: ['\u0e58', '.'], # Thai_lekpaet 0x0df9: ['\u0e59', '.'], # Thai_lekkao 0x0ea1: ['\u3131', 'f'], # Hangul_Kiyeog 0x0ea2: ['\u3132', 'f'], # Hangul_SsangKiyeog 0x0ea3: ['\u3133', 'f'], # Hangul_KiyeogSios 0x0ea4: ['\u3134', 'f'], # Hangul_Nieun 0x0ea5: ['\u3135', 'f'], # Hangul_NieunJieuj 0x0ea6: ['\u3136', 'f'], # Hangul_NieunHieuh 0x0ea7: ['\u3137', 'f'], # Hangul_Dikeud 0x0ea8: ['\u3138', 'f'], # Hangul_SsangDikeud 0x0ea9: ['\u3139', 'f'], # Hangul_Rieul 0x0eaa: ['\u313a', 'f'], # Hangul_RieulKiyeog 0x0eab: ['\u313b', 'f'], # Hangul_RieulMieum 0x0eac: ['\u313c', 'f'], # Hangul_RieulPieub 0x0ead: ['\u313d', 'f'], # Hangul_RieulSios 0x0eae: ['\u313e', 'f'], # Hangul_RieulTieut 0x0eaf: ['\u313f', 'f'], # Hangul_RieulPhieuf 0x0eb0: ['\u3140', 'f'], # Hangul_RieulHieuh 0x0eb1: ['\u3141', 'f'], # Hangul_Mieum 0x0eb2: ['\u3142', 'f'], # Hangul_Pieub 0x0eb3: ['\u3143', 'f'], # Hangul_SsangPieub 0x0eb4: ['\u3144', 'f'], # Hangul_PieubSios 0x0eb5: ['\u3145', 'f'], # Hangul_Sios 0x0eb6: ['\u3146', 'f'], # Hangul_SsangSios 0x0eb7: ['\u3147', 'f'], # Hangul_Ieung 0x0eb8: ['\u3148', 'f'], # Hangul_Jieuj 0x0eb9: ['\u3149', 'f'], # Hangul_SsangJieuj 0x0eba: ['\u314a', 'f'], # Hangul_Cieuc 0x0ebb: ['\u314b', 'f'], # Hangul_Khieuq 0x0ebc: ['\u314c', 'f'], # Hangul_Tieut 0x0ebd: ['\u314d', 'f'], # Hangul_Phieuf 0x0ebe: ['\u314e', 'f'], # Hangul_Hieuh 0x0ebf: ['\u314f', 'f'], # Hangul_A 0x0ec0: ['\u3150', 'f'], # Hangul_AE 0x0ec1: ['\u3151', 'f'], # Hangul_YA 0x0ec2: ['\u3152', 'f'], # Hangul_YAE 0x0ec3: ['\u3153', 'f'], # Hangul_EO 0x0ec4: ['\u3154', 'f'], # Hangul_E 0x0ec5: ['\u3155', 'f'], # Hangul_YEO 0x0ec6: ['\u3156', 'f'], # Hangul_YE 0x0ec7: ['\u3157', 'f'], # Hangul_O 0x0ec8: ['\u3158', 'f'], # Hangul_WA 0x0ec9: ['\u3159', 'f'], # Hangul_WAE 0x0eca: ['\u315a', 'f'], # Hangul_OE 0x0ecb: ['\u315b', 'f'], # Hangul_YO 0x0ecc: ['\u315c', 'f'], # Hangul_U 0x0ecd: ['\u315d', 'f'], # Hangul_WEO 0x0ece: ['\u315e', 'f'], # Hangul_WE 0x0ecf: ['\u315f', 'f'], # Hangul_WI 0x0ed0: ['\u3160', 'f'], # Hangul_YU 0x0ed1: ['\u3161', 'f'], # Hangul_EU 0x0ed2: ['\u3162', 'f'], # Hangul_YI 0x0ed3: ['\u3163', 'f'], # Hangul_I 0x0ed4: ['\u11a8', 'f'], # Hangul_J_Kiyeog 0x0ed5: ['\u11a9', 'f'], # Hangul_J_SsangKiyeog 0x0ed6: ['\u11aa', 'f'], # Hangul_J_KiyeogSios 0x0ed7: ['\u11ab', 'f'], # Hangul_J_Nieun 0x0ed8: ['\u11ac', 'f'], # Hangul_J_NieunJieuj 0x0ed9: ['\u11ad', 'f'], # Hangul_J_NieunHieuh 0x0eda: ['\u11ae', 'f'], # Hangul_J_Dikeud 0x0edb: ['\u11af', 'f'], # Hangul_J_Rieul 0x0edc: ['\u11b0', 'f'], # Hangul_J_RieulKiyeog 0x0edd: ['\u11b1', 'f'], # Hangul_J_RieulMieum 0x0ede: ['\u11b2', 'f'], # Hangul_J_RieulPieub 0x0edf: ['\u11b3', 'f'], # Hangul_J_RieulSios 0x0ee0: ['\u11b4', 'f'], # Hangul_J_RieulTieut 0x0ee1: ['\u11b5', 'f'], # Hangul_J_RieulPhieuf 0x0ee2: ['\u11b6', 'f'], # Hangul_J_RieulHieuh 0x0ee3: ['\u11b7', 'f'], # Hangul_J_Mieum 0x0ee4: ['\u11b8', 'f'], # Hangul_J_Pieub 0x0ee5: ['\u11b9', 'f'], # Hangul_J_PieubSios 0x0ee6: ['\u11ba', 'f'], # Hangul_J_Sios 0x0ee7: ['\u11bb', 'f'], # Hangul_J_SsangSios 0x0ee8: ['\u11bc', 'f'], # Hangul_J_Ieung 0x0ee9: ['\u11bd', 'f'], # Hangul_J_Jieuj 0x0eea: ['\u11be', 'f'], # Hangul_J_Cieuc 0x0eeb: ['\u11bf', 'f'], # Hangul_J_Khieuq 0x0eec: ['\u11c0', 'f'], # Hangul_J_Tieut 0x0eed: ['\u11c1', 'f'], # Hangul_J_Phieuf 0x0eee: ['\u11c2', 'f'], # Hangul_J_Hieuh 0x0eef: ['\u316d', 'f'], # Hangul_RieulYeorinHieuh 0x0ef0: ['\u3171', 'f'], # Hangul_SunkyeongeumMieum 0x0ef1: ['\u3178', 'f'], # Hangul_SunkyeongeumPieub 0x0ef2: ['\u317f', 'f'], # Hangul_PanSios 0x0ef3: ['\u3181', 'f'], # Hangul_KkogjiDalrinIeung 0x0ef4: ['\u3184', 'f'], # Hangul_SunkyeongeumPhieuf 0x0ef5: ['\u3186', 'f'], # Hangul_YeorinHieuh 0x0ef6: ['\u318d', 'f'], # Hangul_AraeA 0x0ef7: ['\u318e', 'f'], # Hangul_AraeAE 0x0ef8: ['\u11eb', 'f'], # Hangul_J_PanSios 0x0ef9: ['\u11f0', 'f'], # Hangul_J_KkogjiDalrinIeung 0x0efa: ['\u11f9', 'f'], # Hangul_J_YeorinHieuh 0x0eff: ['\u20a9', 'o'], # Korean_Won 0x13bc: ['\u0152', '.'], # OE 0x13bd: ['\u0153', '.'], # oe 0x13be: ['\u0178', '.'], # Ydiaeresis 0x20a0: ['\u20a0', 'u'], # EcuSign 0x20a1: ['\u20a1', 'u'], # ColonSign 0x20a2: ['\u20a2', 'u'], # CruzeiroSign 0x20a3: ['\u20a3', 'u'], # FFrancSign 0x20a4: ['\u20a4', 'u'], # LiraSign 0x20a5: ['\u20a5', 'u'], # MillSign 0x20a6: ['\u20a6', 'u'], # NairaSign 0x20a7: ['\u20a7', 'u'], # PesetaSign 0x20a8: ['\u20a8', 'u'], # RupeeSign 0x20a9: ['\u20a9', 'u'], # WonSign 0x20aa: ['\u20aa', 'u'], # NewSheqelSign 0x20ab: ['\u20ab', 'u'], # DongSign 0x20ac: ['\u20ac', '.'], # EuroSign 0xfd01: [None , 'f'], # 3270_Duplicate 0xfd02: [None , 'f'], # 3270_FieldMark 0xfd03: [None , 'f'], # 3270_Right2 0xfd04: [None , 'f'], # 3270_Left2 0xfd05: [None , 'f'], # 3270_BackTab 0xfd06: [None , 'f'], # 3270_EraseEOF 0xfd07: [None , 'f'], # 3270_EraseInput 0xfd08: [None , 'f'], # 3270_Reset 0xfd09: [None , 'f'], # 3270_Quit 0xfd0a: [None , 'f'], # 3270_PA1 0xfd0b: [None , 'f'], # 3270_PA2 0xfd0c: [None , 'f'], # 3270_PA3 0xfd0d: [None , 'f'], # 3270_Test 0xfd0e: [None , 'f'], # 3270_Attn 0xfd0f: [None , 'f'], # 3270_CursorBlink 0xfd10: [None , 'f'], # 3270_AltCursor 0xfd11: [None , 'f'], # 3270_KeyClick 0xfd12: [None , 'f'], # 3270_Jump 0xfd13: [None , 'f'], # 3270_Ident 0xfd14: [None , 'f'], # 3270_Rule 0xfd15: [None , 'f'], # 3270_Copy 0xfd16: [None , 'f'], # 3270_Play 0xfd17: [None , 'f'], # 3270_Setup 0xfd18: [None , 'f'], # 3270_Record 0xfd19: [None , 'f'], # 3270_ChangeScreen 0xfd1a: [None , 'f'], # 3270_DeleteWord 0xfd1b: [None , 'f'], # 3270_ExSelect 0xfd1c: [None , 'f'], # 3270_CursorSelect 0xfd1d: [None , 'f'], # 3270_PrintScreen 0xfd1e: [None , 'f'], # 3270_Enter 0xfe01: [None , 'f'], # ISO_Lock 0xfe02: [None , 'f'], # ISO_Level2_Latch 0xfe03: [None , 'f'], # ISO_Level3_Shift 0xfe04: [None , 'f'], # ISO_Level3_Latch 0xfe05: [None , 'f'], # ISO_Level3_Lock 0xfe06: [None , 'f'], # ISO_Group_Latch 0xfe07: [None , 'f'], # ISO_Group_Lock 0xfe08: [None , 'f'], # ISO_Next_Group 0xfe09: [None , 'f'], # ISO_Next_Group_Lock 0xfe0a: [None , 'f'], # ISO_Prev_Group 0xfe0b: [None , 'f'], # ISO_Prev_Group_Lock 0xfe0c: [None , 'f'], # ISO_First_Group 0xfe0d: [None , 'f'], # ISO_First_Group_Lock 0xfe0e: [None , 'f'], # ISO_Last_Group 0xfe0f: [None , 'f'], # ISO_Last_Group_Lock 0xfe20: [None , 'f'], # ISO_Left_Tab 0xfe21: [None , 'f'], # ISO_Move_Line_Up 0xfe22: [None , 'f'], # ISO_Move_Line_Down 0xfe23: [None , 'f'], # ISO_Partial_Line_Up 0xfe24: [None , 'f'], # ISO_Partial_Line_Down 0xfe25: [None , 'f'], # ISO_Partial_Space_Left 0xfe26: [None , 'f'], # ISO_Partial_Space_Right 0xfe27: [None , 'f'], # ISO_Set_Margin_Left 0xfe28: [None , 'f'], # ISO_Set_Margin_Right 0xfe29: [None , 'f'], # ISO_Release_Margin_Left 0xfe2a: [None , 'f'], # ISO_Release_Margin_Right 0xfe2b: [None , 'f'], # ISO_Release_Both_Margins 0xfe2c: [None , 'f'], # ISO_Fast_Cursor_Left 0xfe2d: [None , 'f'], # ISO_Fast_Cursor_Right 0xfe2e: [None , 'f'], # ISO_Fast_Cursor_Up 0xfe2f: [None , 'f'], # ISO_Fast_Cursor_Down 0xfe30: [None , 'f'], # ISO_Continuous_Underline 0xfe31: [None , 'f'], # ISO_Discontinuous_Underline 0xfe32: [None , 'f'], # ISO_Emphasize 0xfe33: [None , 'f'], # ISO_Center_Object 0xfe34: [None , 'f'], # ISO_Enter 0xfe50: ['\u0300', 'f'], # dead_grave 0xfe51: ['\u0301', 'f'], # dead_acute 0xfe52: ['\u0302', 'f'], # dead_circumflex 0xfe53: ['\u0303', 'f'], # dead_tilde 0xfe54: ['\u0304', 'f'], # dead_macron 0xfe55: ['\u0306', 'f'], # dead_breve 0xfe56: ['\u0307', 'f'], # dead_abovedot 0xfe57: ['\u0308', 'f'], # dead_diaeresis 0xfe58: ['\u030a', 'f'], # dead_abovering 0xfe59: ['\u030b', 'f'], # dead_doubleacute 0xfe5a: ['\u030c', 'f'], # dead_caron 0xfe5b: ['\u0327', 'f'], # dead_cedilla 0xfe5c: ['\u0328', 'f'], # dead_ogonek 0xfe5d: ['\u0345', 'f'], # dead_iota 0xfe5e: ['\u3099', 'f'], # dead_voiced_sound 0xfe5f: ['\u309a', 'f'], # dead_semivoiced_sound 0xfe70: [None , 'f'], # AccessX_Enable 0xfe71: [None , 'f'], # AccessX_Feedback_Enable 0xfe72: [None , 'f'], # RepeatKeys_Enable 0xfe73: [None , 'f'], # SlowKeys_Enable 0xfe74: [None , 'f'], # BounceKeys_Enable 0xfe75: [None , 'f'], # StickyKeys_Enable 0xfe76: [None , 'f'], # MouseKeys_Enable 0xfe77: [None , 'f'], # MouseKeys_Accel_Enable 0xfe78: [None , 'f'], # Overlay1_Enable 0xfe79: [None , 'f'], # Overlay2_Enable 0xfe7a: [None , 'f'], # AudibleBell_Enable 0xfed0: [None , 'f'], # First_Virtual_Screen 0xfed1: [None , 'f'], # Prev_Virtual_Screen 0xfed2: [None , 'f'], # Next_Virtual_Screen 0xfed4: [None , 'f'], # Last_Virtual_Screen 0xfed5: [None , 'f'], # Terminate_Server 0xfee0: [None , 'f'], # Pointer_Left 0xfee1: [None , 'f'], # Pointer_Right 0xfee2: [None , 'f'], # Pointer_Up 0xfee3: [None , 'f'], # Pointer_Down 0xfee4: [None , 'f'], # Pointer_UpLeft 0xfee5: [None , 'f'], # Pointer_UpRight 0xfee6: [None , 'f'], # Pointer_DownLeft 0xfee7: [None , 'f'], # Pointer_DownRight 0xfee8: [None , 'f'], # Pointer_Button_Dflt 0xfee9: [None , 'f'], # Pointer_Button1 0xfeea: [None , 'f'], # Pointer_Button2 0xfeeb: [None , 'f'], # Pointer_Button3 0xfeec: [None , 'f'], # Pointer_Button4 0xfeed: [None , 'f'], # Pointer_Button5 0xfeee: [None , 'f'], # Pointer_DblClick_Dflt 0xfeef: [None , 'f'], # Pointer_DblClick1 0xfef0: [None , 'f'], # Pointer_DblClick2 0xfef1: [None , 'f'], # Pointer_DblClick3 0xfef2: [None , 'f'], # Pointer_DblClick4 0xfef3: [None , 'f'], # Pointer_DblClick5 0xfef4: [None , 'f'], # Pointer_Drag_Dflt 0xfef5: [None , 'f'], # Pointer_Drag1 0xfef6: [None , 'f'], # Pointer_Drag2 0xfef7: [None , 'f'], # Pointer_Drag3 0xfef8: [None , 'f'], # Pointer_Drag4 0xfef9: [None , 'f'], # Pointer_EnableKeys 0xfefa: [None , 'f'], # Pointer_Accelerate 0xfefb: [None , 'f'], # Pointer_DfltBtnNext 0xfefc: [None , 'f'], # Pointer_DfltBtnPrev 0xfefd: [None , 'f'], # Pointer_Drag5 0xff08: ['\u0008', 'f'], # BackSpace /* back space, back char */ 0xff09: ['\u0009', 'f'], # Tab 0xff0a: ['\u000a', 'f'], # Linefeed /* Linefeed, LF */ 0xff0b: ['\u000b', 'f'], # Clear 0xff0d: ['\u000d', 'f'], # Return /* Return, enter */ 0xff13: ['\u0013', 'f'], # Pause /* Pause, hold */ 0xff14: ['\u0014', 'f'], # Scroll_Lock 0xff15: ['\u0015', 'f'], # Sys_Req 0xff1b: ['\u001b', 'f'], # Escape 0xff20: [None , 'f'], # Multi_key 0xff21: [None , 'f'], # Kanji 0xff22: [None , 'f'], # Muhenkan 0xff23: [None , 'f'], # Henkan_Mode 0xff24: [None , 'f'], # Romaji 0xff25: [None , 'f'], # Hiragana 0xff26: [None , 'f'], # Katakana 0xff27: [None , 'f'], # Hiragana_Katakana 0xff28: [None , 'f'], # Zenkaku 0xff29: [None , 'f'], # Hankaku 0xff2a: [None , 'f'], # Zenkaku_Hankaku 0xff2b: [None , 'f'], # Touroku 0xff2c: [None , 'f'], # Massyo 0xff2d: [None , 'f'], # Kana_Lock 0xff2e: [None , 'f'], # Kana_Shift 0xff2f: [None , 'f'], # Eisu_Shift 0xff30: [None , 'f'], # Eisu_toggle 0xff31: [None , 'f'], # Hangul 0xff32: [None , 'f'], # Hangul_Start 0xff33: [None , 'f'], # Hangul_End 0xff34: [None , 'f'], # Hangul_Hanja 0xff35: [None , 'f'], # Hangul_Jamo 0xff36: [None , 'f'], # Hangul_Romaja 0xff37: [None , 'f'], # Codeinput 0xff38: [None , 'f'], # Hangul_Jeonja 0xff39: [None , 'f'], # Hangul_Banja 0xff3a: [None , 'f'], # Hangul_PreHanja 0xff3b: [None , 'f'], # Hangul_PostHanja 0xff3c: [None , 'f'], # SingleCandidate 0xff3d: [None , 'f'], # MultipleCandidate 0xff3e: [None , 'f'], # PreviousCandidate 0xff3f: [None , 'f'], # Hangul_Special 0xff50: [None , 'f'], # Home 0xff51: [None , 'f'], # Left 0xff52: [None , 'f'], # Up 0xff53: [None , 'f'], # Right 0xff54: [None , 'f'], # Down 0xff55: [None , 'f'], # Prior 0xff56: [None , 'f'], # Next 0xff57: [None , 'f'], # End 0xff58: [None , 'f'], # Begin 0xff60: [None , 'f'], # Select 0xff61: [None , 'f'], # Print 0xff62: [None , 'f'], # Execute 0xff63: [None , 'f'], # Insert 0xff65: [None , 'f'], # Undo 0xff66: [None , 'f'], # Redo 0xff67: [None , 'f'], # Menu 0xff68: [None , 'f'], # Find 0xff69: [None , 'f'], # Cancel 0xff6a: [None , 'f'], # Help 0xff6b: [None , 'f'], # Break 0xff7e: [None , 'f'], # Mode_switch 0xff7f: [None , 'f'], # Num_Lock 0xff80: ['\u0020', 'f'], # KP_Space /* space */ 0xff89: ['\u0009', 'f'], # KP_Tab 0xff8d: ['\u000d', 'f'], # KP_Enter /* enter */ 0xff91: [None , 'f'], # KP_F1 0xff92: [None , 'f'], # KP_F2 0xff93: [None , 'f'], # KP_F3 0xff94: [None , 'f'], # KP_F4 0xff95: [None , 'f'], # KP_Home 0xff96: [None , 'f'], # KP_Left 0xff97: [None , 'f'], # KP_Up 0xff98: [None , 'f'], # KP_Right 0xff99: [None , 'f'], # KP_Down 0xff9a: [None , 'f'], # KP_Prior 0xff9b: [None , 'f'], # KP_Next 0xff9c: [None , 'f'], # KP_End 0xff9d: [None , 'f'], # KP_Begin 0xff9e: [None , 'f'], # KP_Insert 0xff9f: [None , 'f'], # KP_Delete 0xffaa: ['\u002a', 'f'], # KP_Multiply 0xffab: ['\u002b', 'f'], # KP_Add 0xffac: ['\u002c', 'f'], # KP_Separator /* separator, often comma */ 0xffad: ['\u002d', 'f'], # KP_Subtract 0xffae: ['\u002e', 'f'], # KP_Decimal 0xffaf: ['\u002f', 'f'], # KP_Divide 0xffb0: ['\u0030', 'f'], # KP_0 0xffb1: ['\u0031', 'f'], # KP_1 0xffb2: ['\u0032', 'f'], # KP_2 0xffb3: ['\u0033', 'f'], # KP_3 0xffb4: ['\u0034', 'f'], # KP_4 0xffb5: ['\u0035', 'f'], # KP_5 0xffb6: ['\u0036', 'f'], # KP_6 0xffb7: ['\u0037', 'f'], # KP_7 0xffb8: ['\u0038', 'f'], # KP_8 0xffb9: ['\u0039', 'f'], # KP_9 0xffbd: ['\u003d', 'f'], # KP_Equal /* equals */ 0xffbe: [None , 'f'], # F1 0xffbf: [None , 'f'], # F2 0xffc0: [None , 'f'], # F3 0xffc1: [None , 'f'], # F4 0xffc2: [None , 'f'], # F5 0xffc3: [None , 'f'], # F6 0xffc4: [None , 'f'], # F7 0xffc5: [None , 'f'], # F8 0xffc6: [None , 'f'], # F9 0xffc7: [None , 'f'], # F10 0xffc8: [None , 'f'], # F11 0xffc9: [None , 'f'], # F12 0xffca: [None , 'f'], # F13 0xffcb: [None , 'f'], # F14 0xffcc: [None , 'f'], # F15 0xffcd: [None , 'f'], # F16 0xffce: [None , 'f'], # F17 0xffcf: [None , 'f'], # F18 0xffd0: [None , 'f'], # F19 0xffd1: [None , 'f'], # F20 0xffd2: [None , 'f'], # F21 0xffd3: [None , 'f'], # F22 0xffd4: [None , 'f'], # F23 0xffd5: [None , 'f'], # F24 0xffd6: [None , 'f'], # F25 0xffd7: [None , 'f'], # F26 0xffd8: [None , 'f'], # F27 0xffd9: [None , 'f'], # F28 0xffda: [None , 'f'], # F29 0xffdb: [None , 'f'], # F30 0xffdc: [None , 'f'], # F31 0xffdd: [None , 'f'], # F32 0xffde: [None , 'f'], # F33 0xffdf: [None , 'f'], # F34 0xffe0: [None , 'f'], # F35 0xffe1: [None , 'f'], # Shift_L 0xffe2: [None , 'f'], # Shift_R 0xffe3: [None , 'f'], # Control_L 0xffe4: [None , 'f'], # Control_R 0xffe5: [None , 'f'], # Caps_Lock 0xffe6: [None , 'f'], # Shift_Lock 0xffe7: [None , 'f'], # Meta_L 0xffe8: [None , 'f'], # Meta_R 0xffe9: [None , 'f'], # Alt_L 0xffea: [None , 'f'], # Alt_R 0xffeb: [None , 'f'], # Super_L 0xffec: [None , 'f'], # Super_R 0xffed: [None , 'f'], # Hyper_L 0xffee: [None , 'f'], # Hyper_R 0xffff: [None , 'f'], # Delete 0xffffff: [None , 'f'], # VoidSymbol # Various XFree86 extensions since X11R6.4 # http://cvsweb.xfree86.org/cvsweb/xc/include/keysymdef.h # KOI8-U support (Aleksey Novodvorsky, 1999-05-30) # http://cvsweb.xfree86.org/cvsweb/xc/include/keysymdef.h.diff?r1=1.4&r2=1.5 # Used in XFree86's /usr/lib/X11/xkb/symbols/ua mappings 0x06ad: ['\u0491', '.'], # Ukrainian_ghe_with_upturn 0x06bd: ['\u0490', '.'], # Ukrainian_GHE_WITH_UPTURN # Support for armscii-8, ibm-cp1133, mulelao-1, viscii1.1-1, # tcvn-5712, georgian-academy, georgian-ps # (#2843, Pablo Saratxaga , 1999-06-06) # http://cvsweb.xfree86.org/cvsweb/xc/include/keysymdef.h.diff?r1=1.6&r2=1.7 # Armenian # (not used in any XFree86 4.4 kbd layouts, where /usr/lib/X11/xkb/symbols/am # uses directly Unicode-mapped hexadecimal values instead) 0x14a1: [None , 'r'], # Armenian_eternity 0x14a2: ['\u0587', 'u'], # Armenian_ligature_ew 0x14a3: ['\u0589', 'u'], # Armenian_verjaket 0x14a4: ['\u0029', 'r'], # Armenian_parenright 0x14a5: ['\u0028', 'r'], # Armenian_parenleft 0x14a6: ['\u00bb', 'r'], # Armenian_guillemotright 0x14a7: ['\u00ab', 'r'], # Armenian_guillemotleft 0x14a8: ['\u2014', 'r'], # Armenian_em_dash 0x14a9: ['\u002e', 'r'], # Armenian_mijaket 0x14aa: ['\u055d', 'u'], # Armenian_but 0x14ab: ['\u002c', 'r'], # Armenian_comma 0x14ac: ['\u2013', 'r'], # Armenian_en_dash 0x14ad: ['\u058a', 'u'], # Armenian_yentamna 0x14ae: ['\u2026', 'r'], # Armenian_ellipsis 0x14af: ['\u055c', 'u'], # Armenian_amanak 0x14b0: ['\u055b', 'u'], # Armenian_shesht 0x14b1: ['\u055e', 'u'], # Armenian_paruyk 0x14b2: ['\u0531', 'u'], # Armenian_AYB 0x14b3: ['\u0561', 'u'], # Armenian_ayb 0x14b4: ['\u0532', 'u'], # Armenian_BEN 0x14b5: ['\u0562', 'u'], # Armenian_ben 0x14b6: ['\u0533', 'u'], # Armenian_GIM 0x14b7: ['\u0563', 'u'], # Armenian_gim 0x14b8: ['\u0534', 'u'], # Armenian_DA 0x14b9: ['\u0564', 'u'], # Armenian_da 0x14ba: ['\u0535', 'u'], # Armenian_YECH 0x14bb: ['\u0565', 'u'], # Armenian_yech 0x14bc: ['\u0536', 'u'], # Armenian_ZA 0x14bd: ['\u0566', 'u'], # Armenian_za 0x14be: ['\u0537', 'u'], # Armenian_E 0x14bf: ['\u0567', 'u'], # Armenian_e 0x14c0: ['\u0538', 'u'], # Armenian_AT 0x14c1: ['\u0568', 'u'], # Armenian_at 0x14c2: ['\u0539', 'u'], # Armenian_TO 0x14c3: ['\u0569', 'u'], # Armenian_to 0x14c4: ['\u053a', 'u'], # Armenian_ZHE 0x14c5: ['\u056a', 'u'], # Armenian_zhe 0x14c6: ['\u053b', 'u'], # Armenian_INI 0x14c7: ['\u056b', 'u'], # Armenian_ini 0x14c8: ['\u053c', 'u'], # Armenian_LYUN 0x14c9: ['\u056c', 'u'], # Armenian_lyun 0x14ca: ['\u053d', 'u'], # Armenian_KHE 0x14cb: ['\u056d', 'u'], # Armenian_khe 0x14cc: ['\u053e', 'u'], # Armenian_TSA 0x14cd: ['\u056e', 'u'], # Armenian_tsa 0x14ce: ['\u053f', 'u'], # Armenian_KEN 0x14cf: ['\u056f', 'u'], # Armenian_ken 0x14d0: ['\u0540', 'u'], # Armenian_HO 0x14d1: ['\u0570', 'u'], # Armenian_ho 0x14d2: ['\u0541', 'u'], # Armenian_DZA 0x14d3: ['\u0571', 'u'], # Armenian_dza 0x14d4: ['\u0542', 'u'], # Armenian_GHAT 0x14d5: ['\u0572', 'u'], # Armenian_ghat 0x14d6: ['\u0543', 'u'], # Armenian_TCHE 0x14d7: ['\u0573', 'u'], # Armenian_tche 0x14d8: ['\u0544', 'u'], # Armenian_MEN 0x14d9: ['\u0574', 'u'], # Armenian_men 0x14da: ['\u0545', 'u'], # Armenian_HI 0x14db: ['\u0575', 'u'], # Armenian_hi 0x14dc: ['\u0546', 'u'], # Armenian_NU 0x14dd: ['\u0576', 'u'], # Armenian_nu 0x14de: ['\u0547', 'u'], # Armenian_SHA 0x14df: ['\u0577', 'u'], # Armenian_sha 0x14e0: ['\u0548', 'u'], # Armenian_VO 0x14e1: ['\u0578', 'u'], # Armenian_vo 0x14e2: ['\u0549', 'u'], # Armenian_CHA 0x14e3: ['\u0579', 'u'], # Armenian_cha 0x14e4: ['\u054a', 'u'], # Armenian_PE 0x14e5: ['\u057a', 'u'], # Armenian_pe 0x14e6: ['\u054b', 'u'], # Armenian_JE 0x14e7: ['\u057b', 'u'], # Armenian_je 0x14e8: ['\u054c', 'u'], # Armenian_RA 0x14e9: ['\u057c', 'u'], # Armenian_ra 0x14ea: ['\u054d', 'u'], # Armenian_SE 0x14eb: ['\u057d', 'u'], # Armenian_se 0x14ec: ['\u054e', 'u'], # Armenian_VEV 0x14ed: ['\u057e', 'u'], # Armenian_vev 0x14ee: ['\u054f', 'u'], # Armenian_TYUN 0x14ef: ['\u057f', 'u'], # Armenian_tyun 0x14f0: ['\u0550', 'u'], # Armenian_RE 0x14f1: ['\u0580', 'u'], # Armenian_re 0x14f2: ['\u0551', 'u'], # Armenian_TSO 0x14f3: ['\u0581', 'u'], # Armenian_tso 0x14f4: ['\u0552', 'u'], # Armenian_VYUN 0x14f5: ['\u0582', 'u'], # Armenian_vyun 0x14f6: ['\u0553', 'u'], # Armenian_PYUR 0x14f7: ['\u0583', 'u'], # Armenian_pyur 0x14f8: ['\u0554', 'u'], # Armenian_KE 0x14f9: ['\u0584', 'u'], # Armenian_ke 0x14fa: ['\u0555', 'u'], # Armenian_O 0x14fb: ['\u0585', 'u'], # Armenian_o 0x14fc: ['\u0556', 'u'], # Armenian_FE 0x14fd: ['\u0586', 'u'], # Armenian_fe 0x14fe: ['\u055a', 'u'], # Armenian_apostrophe 0x14ff: ['\u00a7', 'r'], # Armenian_section_sign # Gregorian # (not used in any XFree86 4.4 kbd layouts, were /usr/lib/X11/xkb/symbols/ge_* # uses directly Unicode-mapped hexadecimal values instead) 0x15d0: ['\u10d0', 'u'], # Georgian_an 0x15d1: ['\u10d1', 'u'], # Georgian_ban 0x15d2: ['\u10d2', 'u'], # Georgian_gan 0x15d3: ['\u10d3', 'u'], # Georgian_don 0x15d4: ['\u10d4', 'u'], # Georgian_en 0x15d5: ['\u10d5', 'u'], # Georgian_vin 0x15d6: ['\u10d6', 'u'], # Georgian_zen 0x15d7: ['\u10d7', 'u'], # Georgian_tan 0x15d8: ['\u10d8', 'u'], # Georgian_in 0x15d9: ['\u10d9', 'u'], # Georgian_kan 0x15da: ['\u10da', 'u'], # Georgian_las 0x15db: ['\u10db', 'u'], # Georgian_man 0x15dc: ['\u10dc', 'u'], # Georgian_nar 0x15dd: ['\u10dd', 'u'], # Georgian_on 0x15de: ['\u10de', 'u'], # Georgian_par 0x15df: ['\u10df', 'u'], # Georgian_zhar 0x15e0: ['\u10e0', 'u'], # Georgian_rae 0x15e1: ['\u10e1', 'u'], # Georgian_san 0x15e2: ['\u10e2', 'u'], # Georgian_tar 0x15e3: ['\u10e3', 'u'], # Georgian_un 0x15e4: ['\u10e4', 'u'], # Georgian_phar 0x15e5: ['\u10e5', 'u'], # Georgian_khar 0x15e6: ['\u10e6', 'u'], # Georgian_ghan 0x15e7: ['\u10e7', 'u'], # Georgian_qar 0x15e8: ['\u10e8', 'u'], # Georgian_shin 0x15e9: ['\u10e9', 'u'], # Georgian_chin 0x15ea: ['\u10ea', 'u'], # Georgian_can 0x15eb: ['\u10eb', 'u'], # Georgian_jil 0x15ec: ['\u10ec', 'u'], # Georgian_cil 0x15ed: ['\u10ed', 'u'], # Georgian_char 0x15ee: ['\u10ee', 'u'], # Georgian_xan 0x15ef: ['\u10ef', 'u'], # Georgian_jhan 0x15f0: ['\u10f0', 'u'], # Georgian_hae 0x15f1: ['\u10f1', 'u'], # Georgian_he 0x15f2: ['\u10f2', 'u'], # Georgian_hie 0x15f3: ['\u10f3', 'u'], # Georgian_we 0x15f4: ['\u10f4', 'u'], # Georgian_har 0x15f5: ['\u10f5', 'u'], # Georgian_hoe 0x15f6: ['\u10f6', 'u'], # Georgian_fi # Pablo Saratxaga's i18n updates for XFree86 that are used in Mandrake 7.2. # (#4195, Pablo Saratxaga , 2000-10-27) # http://cvsweb.xfree86.org/cvsweb/xc/include/keysymdef.h.diff?r1=1.9&r2=1.10 # Latin-8 # (the *abovedot keysyms are used in /usr/lib/X11/xkb/symbols/ie) 0x12a1: ['\u1e02', 'u'], # Babovedot 0x12a2: ['\u1e03', 'u'], # babovedot 0x12a6: ['\u1e0a', 'u'], # Dabovedot 0x12a8: ['\u1e80', 'u'], # Wgrave 0x12aa: ['\u1e82', 'u'], # Wacute 0x12ab: ['\u1e0b', 'u'], # dabovedot 0x12ac: ['\u1ef2', 'u'], # Ygrave 0x12b0: ['\u1e1e', 'u'], # Fabovedot 0x12b1: ['\u1e1f', 'u'], # fabovedot 0x12b4: ['\u1e40', 'u'], # Mabovedot 0x12b5: ['\u1e41', 'u'], # mabovedot 0x12b7: ['\u1e56', 'u'], # Pabovedot 0x12b8: ['\u1e81', 'u'], # wgrave 0x12b9: ['\u1e57', 'u'], # pabovedot 0x12ba: ['\u1e83', 'u'], # wacute 0x12bb: ['\u1e60', 'u'], # Sabovedot 0x12bc: ['\u1ef3', 'u'], # ygrave 0x12bd: ['\u1e84', 'u'], # Wdiaeresis 0x12be: ['\u1e85', 'u'], # wdiaeresis 0x12bf: ['\u1e61', 'u'], # sabovedot 0x12d0: ['\u0174', 'u'], # Wcircumflex 0x12d7: ['\u1e6a', 'u'], # Tabovedot 0x12de: ['\u0176', 'u'], # Ycircumflex 0x12f0: ['\u0175', 'u'], # wcircumflex 0x12f7: ['\u1e6b', 'u'], # tabovedot 0x12fe: ['\u0177', 'u'], # ycircumflex # Arabic # (of these, in XFree86 4.4 only Arabic_superscript_alef, Arabic_madda_above, # Arabic_hamza_* are actually used, e.g. in /usr/lib/X11/xkb/symbols/syr) 0x0590: ['\u06f0', 'u'], # Farsi_0 0x0591: ['\u06f1', 'u'], # Farsi_1 0x0592: ['\u06f2', 'u'], # Farsi_2 0x0593: ['\u06f3', 'u'], # Farsi_3 0x0594: ['\u06f4', 'u'], # Farsi_4 0x0595: ['\u06f5', 'u'], # Farsi_5 0x0596: ['\u06f6', 'u'], # Farsi_6 0x0597: ['\u06f7', 'u'], # Farsi_7 0x0598: ['\u06f8', 'u'], # Farsi_8 0x0599: ['\u06f9', 'u'], # Farsi_9 0x05a5: ['\u066a', 'u'], # Arabic_percent 0x05a6: ['\u0670', 'u'], # Arabic_superscript_alef 0x05a7: ['\u0679', 'u'], # Arabic_tteh 0x05a8: ['\u067e', 'u'], # Arabic_peh 0x05a9: ['\u0686', 'u'], # Arabic_tcheh 0x05aa: ['\u0688', 'u'], # Arabic_ddal 0x05ab: ['\u0691', 'u'], # Arabic_rreh 0x05ae: ['\u06d4', 'u'], # Arabic_fullstop 0x05b0: ['\u0660', 'u'], # Arabic_0 0x05b1: ['\u0661', 'u'], # Arabic_1 0x05b2: ['\u0662', 'u'], # Arabic_2 0x05b3: ['\u0663', 'u'], # Arabic_3 0x05b4: ['\u0664', 'u'], # Arabic_4 0x05b5: ['\u0665', 'u'], # Arabic_5 0x05b6: ['\u0666', 'u'], # Arabic_6 0x05b7: ['\u0667', 'u'], # Arabic_7 0x05b8: ['\u0668', 'u'], # Arabic_8 0x05b9: ['\u0669', 'u'], # Arabic_9 0x05f3: ['\u0653', 'u'], # Arabic_madda_above 0x05f4: ['\u0654', 'u'], # Arabic_hamza_above 0x05f5: ['\u0655', 'u'], # Arabic_hamza_below 0x05f6: ['\u0698', 'u'], # Arabic_jeh 0x05f7: ['\u06a4', 'u'], # Arabic_veh 0x05f8: ['\u06a9', 'u'], # Arabic_keheh 0x05f9: ['\u06af', 'u'], # Arabic_gaf 0x05fa: ['\u06ba', 'u'], # Arabic_noon_ghunna 0x05fb: ['\u06be', 'u'], # Arabic_heh_doachashmee 0x05fc: ['\u06cc', 'u'], # Farsi_yeh 0x05fd: ['\u06d2', 'u'], # Arabic_yeh_baree 0x05fe: ['\u06c1', 'u'], # Arabic_heh_goal # Cyrillic # (none of these are actually used in any XFree86 4.4 kbd layouts) 0x0680: ['\u0492', 'u'], # Cyrillic_GHE_bar 0x0681: ['\u0496', 'u'], # Cyrillic_ZHE_descender 0x0682: ['\u049a', 'u'], # Cyrillic_KA_descender 0x0683: ['\u049c', 'u'], # Cyrillic_KA_vertstroke 0x0684: ['\u04a2', 'u'], # Cyrillic_EN_descender 0x0685: ['\u04ae', 'u'], # Cyrillic_U_straight 0x0686: ['\u04b0', 'u'], # Cyrillic_U_straight_bar 0x0687: ['\u04b2', 'u'], # Cyrillic_HA_descender 0x0688: ['\u04b6', 'u'], # Cyrillic_CHE_descender 0x0689: ['\u04b8', 'u'], # Cyrillic_CHE_vertstroke 0x068a: ['\u04ba', 'u'], # Cyrillic_SHHA 0x068c: ['\u04d8', 'u'], # Cyrillic_SCHWA 0x068d: ['\u04e2', 'u'], # Cyrillic_I_macron 0x068e: ['\u04e8', 'u'], # Cyrillic_O_bar 0x068f: ['\u04ee', 'u'], # Cyrillic_U_macron 0x0690: ['\u0493', 'u'], # Cyrillic_ghe_bar 0x0691: ['\u0497', 'u'], # Cyrillic_zhe_descender 0x0692: ['\u049b', 'u'], # Cyrillic_ka_descender 0x0693: ['\u049d', 'u'], # Cyrillic_ka_vertstroke 0x0694: ['\u04a3', 'u'], # Cyrillic_en_descender 0x0695: ['\u04af', 'u'], # Cyrillic_u_straight 0x0696: ['\u04b1', 'u'], # Cyrillic_u_straight_bar 0x0697: ['\u04b3', 'u'], # Cyrillic_ha_descender 0x0698: ['\u04b7', 'u'], # Cyrillic_che_descender 0x0699: ['\u04b9', 'u'], # Cyrillic_che_vertstroke 0x069a: ['\u04bb', 'u'], # Cyrillic_shha 0x069c: ['\u04d9', 'u'], # Cyrillic_schwa 0x069d: ['\u04e3', 'u'], # Cyrillic_i_macron 0x069e: ['\u04e9', 'u'], # Cyrillic_o_bar 0x069f: ['\u04ef', 'u'], # Cyrillic_u_macron # Caucasus # (of these, in XFree86 4.4 only Gcaron, gcaron are actually used, # e.g. in /usr/lib/X11/xkb/symbols/sapmi; the lack of Unicode # equivalents for the others suggests that they are bogus) 0x16a2: [None , 'r'], # Ccedillaabovedot 0x16a3: ['\u1e8a', 'u'], # Xabovedot 0x16a5: [None , 'r'], # Qabovedot 0x16a6: ['\u012c', 'u'], # Ibreve 0x16a7: [None , 'r'], # IE 0x16a8: [None , 'r'], # UO 0x16a9: ['\u01b5', 'u'], # Zstroke 0x16aa: ['\u01e6', 'u'], # Gcaron 0x16af: ['\u019f', 'u'], # Obarred 0x16b2: [None , 'r'], # ccedillaabovedot 0x16b3: ['\u1e8b', 'u'], # xabovedot 0x16b4: [None , 'r'], # Ocaron 0x16b5: [None , 'r'], # qabovedot 0x16b6: ['\u012d', 'u'], # ibreve 0x16b7: [None , 'r'], # ie 0x16b8: [None , 'r'], # uo 0x16b9: ['\u01b6', 'u'], # zstroke 0x16ba: ['\u01e7', 'u'], # gcaron 0x16bd: ['\u01d2', 'u'], # ocaron 0x16bf: ['\u0275', 'u'], # obarred 0x16c6: ['\u018f', 'u'], # SCHWA 0x16f6: ['\u0259', 'u'], # schwa # Inupiak, Guarani # (none of these are actually used in any XFree86 4.4 kbd layouts, # and the lack of Unicode equivalents suggests that they are bogus) 0x16d1: ['\u1e36', 'u'], # Lbelowdot 0x16d2: [None , 'r'], # Lstrokebelowdot 0x16d3: [None , 'r'], # Gtilde 0x16e1: ['\u1e37', 'u'], # lbelowdot 0x16e2: [None , 'r'], # lstrokebelowdot 0x16e3: [None , 'r'], # gtilde # Vietnamese # (none of these are actually used in any XFree86 4.4 kbd layouts; they are # also pointless, as Vietnamese input methods use dead accent keys + ASCII keys) 0x1ea0: ['\u1ea0', 'u'], # Abelowdot 0x1ea1: ['\u1ea1', 'u'], # abelowdot 0x1ea2: ['\u1ea2', 'u'], # Ahook 0x1ea3: ['\u1ea3', 'u'], # ahook 0x1ea4: ['\u1ea4', 'u'], # Acircumflexacute 0x1ea5: ['\u1ea5', 'u'], # acircumflexacute 0x1ea6: ['\u1ea6', 'u'], # Acircumflexgrave 0x1ea7: ['\u1ea7', 'u'], # acircumflexgrave 0x1ea8: ['\u1ea8', 'u'], # Acircumflexhook 0x1ea9: ['\u1ea9', 'u'], # acircumflexhook 0x1eaa: ['\u1eaa', 'u'], # Acircumflextilde 0x1eab: ['\u1eab', 'u'], # acircumflextilde 0x1eac: ['\u1eac', 'u'], # Acircumflexbelowdot 0x1ead: ['\u1ead', 'u'], # acircumflexbelowdot 0x1eae: ['\u1eae', 'u'], # Abreveacute 0x1eaf: ['\u1eaf', 'u'], # abreveacute 0x1eb0: ['\u1eb0', 'u'], # Abrevegrave 0x1eb1: ['\u1eb1', 'u'], # abrevegrave 0x1eb2: ['\u1eb2', 'u'], # Abrevehook 0x1eb3: ['\u1eb3', 'u'], # abrevehook 0x1eb4: ['\u1eb4', 'u'], # Abrevetilde 0x1eb5: ['\u1eb5', 'u'], # abrevetilde 0x1eb6: ['\u1eb6', 'u'], # Abrevebelowdot 0x1eb7: ['\u1eb7', 'u'], # abrevebelowdot 0x1eb8: ['\u1eb8', 'u'], # Ebelowdot 0x1eb9: ['\u1eb9', 'u'], # ebelowdot 0x1eba: ['\u1eba', 'u'], # Ehook 0x1ebb: ['\u1ebb', 'u'], # ehook 0x1ebc: ['\u1ebc', 'u'], # Etilde 0x1ebd: ['\u1ebd', 'u'], # etilde 0x1ebe: ['\u1ebe', 'u'], # Ecircumflexacute 0x1ebf: ['\u1ebf', 'u'], # ecircumflexacute 0x1ec0: ['\u1ec0', 'u'], # Ecircumflexgrave 0x1ec1: ['\u1ec1', 'u'], # ecircumflexgrave 0x1ec2: ['\u1ec2', 'u'], # Ecircumflexhook 0x1ec3: ['\u1ec3', 'u'], # ecircumflexhook 0x1ec4: ['\u1ec4', 'u'], # Ecircumflextilde 0x1ec5: ['\u1ec5', 'u'], # ecircumflextilde 0x1ec6: ['\u1ec6', 'u'], # Ecircumflexbelowdot 0x1ec7: ['\u1ec7', 'u'], # ecircumflexbelowdot 0x1ec8: ['\u1ec8', 'u'], # Ihook 0x1ec9: ['\u1ec9', 'u'], # ihook 0x1eca: ['\u1eca', 'u'], # Ibelowdot 0x1ecb: ['\u1ecb', 'u'], # ibelowdot 0x1ecc: ['\u1ecc', 'u'], # Obelowdot 0x1ecd: ['\u1ecd', 'u'], # obelowdot 0x1ece: ['\u1ece', 'u'], # Ohook 0x1ecf: ['\u1ecf', 'u'], # ohook 0x1ed0: ['\u1ed0', 'u'], # Ocircumflexacute 0x1ed1: ['\u1ed1', 'u'], # ocircumflexacute 0x1ed2: ['\u1ed2', 'u'], # Ocircumflexgrave 0x1ed3: ['\u1ed3', 'u'], # ocircumflexgrave 0x1ed4: ['\u1ed4', 'u'], # Ocircumflexhook 0x1ed5: ['\u1ed5', 'u'], # ocircumflexhook 0x1ed6: ['\u1ed6', 'u'], # Ocircumflextilde 0x1ed7: ['\u1ed7', 'u'], # ocircumflextilde 0x1ed8: ['\u1ed8', 'u'], # Ocircumflexbelowdot 0x1ed9: ['\u1ed9', 'u'], # ocircumflexbelowdot 0x1eda: ['\u1eda', 'u'], # Ohornacute 0x1edb: ['\u1edb', 'u'], # ohornacute 0x1edc: ['\u1edc', 'u'], # Ohorngrave 0x1edd: ['\u1edd', 'u'], # ohorngrave 0x1ede: ['\u1ede', 'u'], # Ohornhook 0x1edf: ['\u1edf', 'u'], # ohornhook 0x1ee0: ['\u1ee0', 'u'], # Ohorntilde 0x1ee1: ['\u1ee1', 'u'], # ohorntilde 0x1ee2: ['\u1ee2', 'u'], # Ohornbelowdot 0x1ee3: ['\u1ee3', 'u'], # ohornbelowdot 0x1ee4: ['\u1ee4', 'u'], # Ubelowdot 0x1ee5: ['\u1ee5', 'u'], # ubelowdot 0x1ee6: ['\u1ee6', 'u'], # Uhook 0x1ee7: ['\u1ee7', 'u'], # uhook 0x1ee8: ['\u1ee8', 'u'], # Uhornacute 0x1ee9: ['\u1ee9', 'u'], # uhornacute 0x1eea: ['\u1eea', 'u'], # Uhorngrave 0x1eeb: ['\u1eeb', 'u'], # uhorngrave 0x1eec: ['\u1eec', 'u'], # Uhornhook 0x1eed: ['\u1eed', 'u'], # uhornhook 0x1eee: ['\u1eee', 'u'], # Uhorntilde 0x1eef: ['\u1eef', 'u'], # uhorntilde 0x1ef0: ['\u1ef0', 'u'], # Uhornbelowdot 0x1ef1: ['\u1ef1', 'u'], # uhornbelowdot 0x1ef4: ['\u1ef4', 'u'], # Ybelowdot 0x1ef5: ['\u1ef5', 'u'], # ybelowdot 0x1ef6: ['\u1ef6', 'u'], # Yhook 0x1ef7: ['\u1ef7', 'u'], # yhook 0x1ef8: ['\u1ef8', 'u'], # Ytilde 0x1ef9: ['\u1ef9', 'u'], # ytilde 0x1efa: ['\u01a0', 'u'], # Ohorn 0x1efb: ['\u01a1', 'u'], # ohorn 0x1efc: ['\u01af', 'u'], # Uhorn 0x1efd: ['\u01b0', 'u'], # uhorn # (Unicode combining characters have no direct equivalence with # keysyms, where dead keys are defined instead) 0x1e9f: ['\u0303', 'r'], # combining_tilde 0x1ef2: ['\u0300', 'r'], # combining_grave 0x1ef3: ['\u0301', 'r'], # combining_acute 0x1efe: ['\u0309', 'r'], # combining_hook 0x1eff: ['\u0323', 'r'], # combining_belowdot # These probably should be added to the X11 standard properly, # as they could be of use for Vietnamese input methods. 0xfe60: ['\u0323', 'f'], # dead_belowdot 0xfe61: ['\u0309', 'f'], # dead_hook 0xfe62: ['\u031b', 'f'], # dead_horn } screenkey-v1.5/Screenkey/labelmanager.py000066400000000000000000000637261415444532700205000ustar00rootroot00000000000000# "screenkey" is distributed under GNU GPLv3+, WITHOUT ANY WARRANTY. # Copyright(c) 2010-2012: Pablo Seminario # Copyright(c) 2015-2016: wave++ "Yuri D'Elia" # Copyright(c) 2019-2020: Yuto Tokunaga from . import inputlistener from .inputlistener import InputListener, InputType from gi.repository import GLib from collections import namedtuple from datetime import datetime # Key replacement data: # # bk_stop: stops backspace processing in baked mode, but not full mode # these keys generally move the caret, and are also padded with a thin space # silent: always stops backspace processing (baked/full mode) # these keys generally do not emit output in the text and cannot be processed # spaced: strong spacing is required around the symbol ReplData = namedtuple('ReplData', ['value', 'font', 'suffix']) KeyRepl = namedtuple('KeyRepl', ['bk_stop', 'silent', 'spaced', 'repl']) KeyData = namedtuple('KeyData', ['stamp', 'is_ctrl', 'bk_stop', 'silent', 'spaced', 'markup']) ButtonData = namedtuple('ButtonData', ['stamp', 'btn', 'pressed']) REPLACE_SYMS = { # Regular keys 'Escape': KeyRepl(True, True, True, _('Esc')), 'Tab': KeyRepl(True, False, False, _('↹')), 'ISO_Left_Tab': KeyRepl(True, False, False, _('↹')), 'Return': KeyRepl(True, False, False, _('⏎')), 'space': KeyRepl(False, False, False, _('␣')), 'BackSpace': KeyRepl(True, True, False, _('⌫')), 'Caps_Lock': KeyRepl(True, True, True, _('Caps')), 'F1': KeyRepl(True, True, True, _('F1')), 'F2': KeyRepl(True, True, True, _('F2')), 'F3': KeyRepl(True, True, True, _('F3')), 'F4': KeyRepl(True, True, True, _('F4')), 'F5': KeyRepl(True, True, True, _('F5')), 'F6': KeyRepl(True, True, True, _('F6')), 'F7': KeyRepl(True, True, True, _('F7')), 'F8': KeyRepl(True, True, True, _('F8')), 'F9': KeyRepl(True, True, True, _('F9')), 'F10': KeyRepl(True, True, True, _('F10')), 'F11': KeyRepl(True, True, True, _('F11')), 'F12': KeyRepl(True, True, True, _('F12')), 'Up': KeyRepl(True, True, False, _('↑')), 'Left': KeyRepl(True, True, False, _('←')), 'Right': KeyRepl(True, True, False, _('→')), 'Down': KeyRepl(True, True, False, _('↓')), 'Prior': KeyRepl(True, True, True, _('PgUp')), 'Next': KeyRepl(True, True, True, _('PgDn')), 'Home': KeyRepl(True, True, True, _('Home')), 'End': KeyRepl(True, True, True, _('End')), 'Insert': KeyRepl(False, True, True, _('Ins')), 'Delete': KeyRepl(True, False, True, _('Del')), 'KP_End': KeyRepl(False, False, True, _('1ᴷᴾ')), 'KP_Down': KeyRepl(False, False, True, _('2ᴷᴾ')), 'KP_Next': KeyRepl(False, False, True, _('3ᴷᴾ')), 'KP_Left': KeyRepl(False, False, True, _('4ᴷᴾ')), 'KP_Begin': KeyRepl(False, False, True, _('5ᴷᴾ')), 'KP_Right': KeyRepl(False, False, True, _('6ᴷᴾ')), 'KP_Home': KeyRepl(False, False, True, _('7ᴷᴾ')), 'KP_Up': KeyRepl(False, False, True, _('8ᴷᴾ')), 'KP_Prior': KeyRepl(False, False, True, _('9ᴷᴾ')), 'KP_Insert': KeyRepl(False, False, True, _('0ᴷᴾ')), 'KP_Delete': KeyRepl(False, False, True, _('(.)')), 'KP_Add': KeyRepl(False, False, True, _('(+)')), 'KP_Subtract': KeyRepl(False, False, True, _('(-)')), 'KP_Multiply': KeyRepl(False, False, True, _('(*)')), 'KP_Divide': KeyRepl(False, False, True, _('(/)')), 'KP_Enter': KeyRepl(True, False, False, _('⏎')), 'KP_1': KeyRepl(False, False, True, _('1ᴷᴾ')), 'KP_2': KeyRepl(False, False, True, _('2ᴷᴾ')), 'KP_3': KeyRepl(False, False, True, _('3ᴷᴾ')), 'KP_4': KeyRepl(False, False, True, _('4ᴷᴾ')), 'KP_5': KeyRepl(False, False, True, _('5ᴷᴾ')), 'KP_6': KeyRepl(False, False, True, _('6ᴷᴾ')), 'KP_7': KeyRepl(False, False, True, _('7ᴷᴾ')), 'KP_8': KeyRepl(False, False, True, _('8ᴷᴾ')), 'KP_9': KeyRepl(False, False, True, _('9ᴷᴾ')), 'KP_0': KeyRepl(False, False, True, _('0ᴷᴾ')), 'Num_Lock': KeyRepl(False, True, True, _('NumLck')), 'Scroll_Lock': KeyRepl(False, True, True, _('ScrLck')), 'Pause': KeyRepl(False, True, True, _('Pause')), 'Break': KeyRepl(False, True, True, _('Break')), 'Print': KeyRepl(False, True, True, _('Print')), 'Multi_key': KeyRepl(False, True, True, _('Compose')), # Multimedia keys 'XF86AudioMute': KeyRepl(True, True, True, [ReplData(_('\uf026'), 'Font Awesome 5 Free', None), ReplData(_('\uf026'), 'FontAwesome', None), ReplData(_('Mute'), None, None)]), 'XF86AudioMicMute': KeyRepl(True, True, True, [ReplData(_('\uf131'), 'Font Awesome 5 Free', None), ReplData(_('\uf131'), 'FontAwesome', None), ReplData(_('Rec'), None, None)]), 'XF86AudioRaiseVolume': KeyRepl(True, True, True, [ReplData(_('\uf028'), 'Font Awesome 5 Free', None), ReplData(_('\uf028'), 'FontAwesome', None), ReplData(_('Vol'), None, '+')]), 'XF86AudioLowerVolume': KeyRepl(True, True, True, [ReplData(_('\uf027'), 'Font Awesome 5 Free', None), ReplData(_('\uf027'), 'FontAwesome', None), ReplData(_('Vol'), None, '-')]), 'XF86AudioPrev': KeyRepl(True, True, True, [ReplData(_('\uf048'), 'Font Awesome 5 Free', None), ReplData(_('\uf048'), 'FontAwesome', None), ReplData(_('Prev'), None, None)]), 'XF86AudioNext': KeyRepl(True, True, True, [ReplData(_('\uf051'), 'Font Awesome 5 Free', None), ReplData(_('\uf051'), 'FontAwesome', None), ReplData(_('Next'), None, None)]), 'XF86AudioPlay': KeyRepl(True, True, True, [ReplData(_('\uf04b'), 'Font Awesome 5 Free', None), ReplData(_('\uf04b'), 'FontAwesome', None), ReplData(_('▶'), None, None)]), 'XF86AudioStop': KeyRepl(True, True, True, [ReplData(_('\uf04d'), 'Font Awesome 5 Free', None), ReplData(_('\uf04d'), 'FontAwesome', None), ReplData(_('⬛'), None, None)]), 'XF86Eject': KeyRepl(True, True, True, [ReplData(_('\uf052'), 'Font Awesome 5 Free', None), ReplData(_('\uf052'), 'FontAwesome', None), ReplData(_('Eject'), None, None)]), 'XF86MonBrightnessDown': KeyRepl(True, True, True, [ReplData(_('\uf185'), 'Font Awesome 5 Free', '-'), ReplData(_('\uf185'), 'FontAwesome', '-'), ReplData(_('Bright'), None, '-')]), 'XF86MonBrightnessUp': KeyRepl(True, True, True, [ReplData(_('\uf185'), 'Font Awesome 5 Free', '+'), ReplData(_('\uf185'), 'FontAwesome', '+'), ReplData(_('Bright'), None, '+')]), 'XF86Display': KeyRepl(True, True, True, [ReplData(_('\uf108'), 'Font Awesome 5 Free', None), ReplData(_('\uf108'), 'FontAwesome', None), ReplData(_('Display'), None, None)]), 'XF86WLAN': KeyRepl(True, True, True, [ReplData(_('\uf1eb'), 'Font Awesome 5 Free', None), ReplData(_('\uf1eb'), 'FontAwesome', None), ReplData(_('WLAN'), None, None)]), 'XF86Search': KeyRepl(True, True, True, [ReplData(_('\uf002'), 'Font Awesome 5 Free', None), ReplData(_('\uf002'), 'FontAwesome', None), ReplData(_('Search'), None, None)]), 'XF86Bluetooth': KeyRepl(True, True, True, [ReplData(_('\uf294'), 'Font Awesome 5 Free', None), ReplData(_('\uf294'), 'FontAwesome', None), ReplData(_('Bluetooth'), None, None)]), 'XF86Tools': KeyRepl(True, True, True, [ReplData(_('\uf7d9'), 'Font Awesome 5 Free', None), ReplData(_('🛠'), None, None)]), 'XF86Favorites': KeyRepl(True, True, True, [ReplData(_('\uf005'), 'Font Awesome 5 Free', None), ReplData(_('\uf005'), 'FontAwesome', None), ReplData(_('🟊'), None, None)]), } WHITESPACE_SYMS = {'Tab', 'ISO_Left_Tab', 'Return', 'space', 'KP_Enter'} MODS_SYMS = { 'shift': {'Shift_L', 'Shift_R'}, 'ctrl': {'Control_L', 'Control_R'}, 'alt': {'Alt_L', 'Alt_R', 'Meta_L', 'Meta_R'}, 'super': {'Super_L', 'Super_R'}, 'hyper': {'Hyper_L', 'Hyper_R'}, 'alt_gr': {'ISO_Level3_Shift'}, } REPLACE_MODS = { 'shift': {'normal': _('Shift+'), 'emacs': 'S-', 'mac': _('⇧+')}, 'ctrl': {'normal': _('Ctrl+'), 'emacs': 'C-', 'mac': _('⌘+')}, 'alt': {'normal': _('Alt+'), 'emacs': 'M-', 'mac': _('⌥+')}, 'super': {'normal': _('Super+'), 'emacs': 's-', 'win': [ReplData(_('\uf17a'), 'Font Awesome 5 Free', '+'), ReplData(_('\uf17a'), 'FontAwesome', '+'), ReplData(_('Win'), None, '+')], 'tux': [ReplData(_('\uf17c'), 'Font Awesome 5 Free', '+'), ReplData(_('\uf17c'), 'FontAwesome', '+'), ReplData(_('Super'), None, '+')]}, 'hyper': {'normal': _('Hyper+'), 'emacs': 'H-'}, 'alt_gr': {'normal': _('AltGr+'), 'emacs': 'AltGr-'}, } def keysym_to_mod(keysym): for k, v in MODS_SYMS.items(): if keysym in v: return k return None class LabelManager: def __init__(self, label_listener, image_listener, logger, key_mode, bak_mode, mods_mode, mods_only, multiline, vis_shift, vis_space, recent_thr, compr_cnt, ignore, pango_ctx, enabled): self.key_mode = key_mode self.bak_mode = bak_mode self.mods_mode = mods_mode self.logger = logger self.label_listener = label_listener self.image_listener = image_listener self.data = [] self.enabled = enabled self.mods_only = mods_only self.multiline = multiline self.vis_shift = vis_shift self.vis_space = vis_space self.recent_thr = recent_thr self.compr_cnt = compr_cnt self.ignore = ignore self.kl = None self.font_families = {x.get_name() for x in pango_ctx.list_families()} self.update_replacement_map() def __del__(self): self.stop() def start(self): self.stop() compose = (self.key_mode == 'composed') translate = (self.key_mode in ['composed', 'translated']) self.kl = InputListener(self.event_handler, InputType.keyboard | InputType.button, compose, translate) self.kl.start() self.logger.debug("Thread started.") def stop(self): if self.kl: self.kl.stop() self.logger.debug("Thread stopped.") self.kl.join() self.kl = None def clear(self): self.data = [] def get_repl_markup(self, repl): if type(repl) != list: repl = [repl] for c in repl: # no replacement data if type(c) != ReplData: return GLib.markup_escape_text(c) # plain suffix if c.suffix is None: sfx = '' else: sfx = GLib.markup_escape_text(c.suffix) if c.font is None: # regular font return GLib.markup_escape_text(c.value) + sfx; elif c.font in self.font_families: # custom symbol return '' + \ GLib.markup_escape_text(c.value) + '' + sfx; def update_replacement_map(self): self.replace_syms = {} for k, v in REPLACE_SYMS.items(): markup = self.get_repl_markup(v.repl) self.replace_syms[k] = KeyRepl(v.bk_stop, v.silent, v.spaced, markup) self.replace_mods = {} for k, v in REPLACE_MODS.items(): data = v.get(self.mods_mode, v['normal']) self.replace_mods[k] = self.get_repl_markup(data) def update_text(self, synthetic=False): markup = "" recent = False stamp = datetime.now() repeats = 0 for i, key in enumerate(self.data): if i != 0: last = self.data[i - 1] # compress repeats if self.compr_cnt and key.markup == last.markup: repeats += 1 if repeats < self.compr_cnt: pass elif i == len(self.data) - 1 or key.markup != self.data[i + 1].markup: if not recent and (stamp - key.stamp).total_seconds() < self.recent_thr: markup += '' recent = True markup += '…{}×'.format(repeats + 1) if len(key.markup) and key.markup[-1] == '\n': markup += '\n' continue else: continue # character block spacing if len(last.markup) and last.markup[-1] == '\n': pass elif key.is_ctrl or last.is_ctrl or key.spaced or last.spaced: markup += ' ' elif key.bk_stop or last.bk_stop or repeats > self.compr_cnt: markup += '\u2009' if key.markup != last.markup: repeats = 0 key_markup = key.markup if type(key_markup) is bytes: key_markup = key_markup.decode() if not recent and (stamp - key.stamp).total_seconds() < self.recent_thr: recent = True key_markup = '' + key_markup # disable ligatures if len(key.markup) == 1 and 0x0300 <= ord(key.markup) <= 0x036F: # workaround for pango not handling ZWNJ correctly for combining marks markup += '\u180e' + key_markup + '\u200a' elif len(key_markup): markup += '\u200c' + key_markup if len(markup) and markup[-1] == '\n': markup = markup.rstrip('\n') if not self.vis_space and not self.data[-1].is_ctrl: # always show some return symbol at the last line markup += self.replace_syms['Return'].repl if recent: markup += '' self.logger.debug("Label updated: %s." % repr(markup)) self.label_listener(markup, synthetic) def queue_update(self): self.update_text(True) def event_handler(self, event): if event is None: self.logger.debug("inputlistener failure: {}".format(str(self.kl.error))) self.label_listener(None, None) return if isinstance(event, inputlistener.KeyData): self.key_press(event) elif isinstance(event, inputlistener.ButtonData): self.btn_press(event) else: self.logger.error("unhandled event type {}".format(type(event))) def key_press(self, event): if event.symbol is None: # TODO: Investigate what causes this to happen. # I caught it once in pdb, but in this function, not in inputlistener, # and KeyData doesn't contain enough info. return symbol = event.symbol.decode() if self.enabled: for mod, button_id in zip(['ctrl', 'alt', 'shift'], range(8, 11)): if symbol in MODS_SYMS[mod]: self.image_listener(ButtonData( datetime.now(), button_id, event.pressed )) if event.pressed == False: self.logger.debug("Key released {:5}(ks): {}".format(event.keysym, symbol)) return if symbol in self.ignore: self.logger.debug("Key ignored {:5}(ks): {}".format(event.keysym, symbol)) return if event.filtered: self.logger.debug("Key filtered {:5}(ks): {}".format(event.keysym, symbol)) else: state = "repeated" if event.repeated else "pressed" string = repr(event.string) self.logger.debug("Key {:8} {:5}(ks): {} ({}, mask: {:08b})".format (state, event.keysym, string, symbol, event.mods_mask)) # Stealth enable/disable handling for mod in ['shift', 'ctrl', 'alt']: if not event.repeated and event.modifiers[mod] \ and symbol in MODS_SYMS[mod]: self.enabled = not self.enabled state = 'enabled' if self.enabled else 'disabled' if not self.enabled: self.image_listener(None) self.logger.info("{mod}+{mod} detected: screenkey {state}".format( mod=mod.capitalize(), state=state)) if not self.enabled: return False # keep the window alive as the user is composing mod_pressed = keysym_to_mod(symbol) is not None update = len(self.data) and (event.filtered or mod_pressed) if not event.filtered: if self.key_mode in ['translated', 'composed']: update |= self.key_normal_mode(event) elif self.key_mode == 'raw': update |= self.key_raw_mode(event) else: update |= self.key_keysyms_mode(event) if update: self.update_text() def key_normal_mode(self, event): self.logger.debug("key_normal_mode") # Visible modifiers mod = '' for cap in ['ctrl', 'alt', 'super', 'hyper']: if event.modifiers[cap]: mod = mod + self.replace_mods[cap] # Backspace handling symbol = event.symbol.decode() if symbol == 'BackSpace' and not self.mods_only and \ mod == '' and not event.modifiers['shift']: key_repl = self.replace_syms.get(symbol) if self.bak_mode == 'normal': self.data.append(KeyData(datetime.now(), False, *key_repl)) return True else: if not len(self.data): pop = False else: last = self.data[-1] if last.is_ctrl: pop = False elif self.bak_mode == 'baked': pop = not last.bk_stop else: pop = not last.silent if pop: self.data.pop() else: self.data.append(KeyData(datetime.now(), False, *key_repl)) return True # Regular keys key_repl = self.replace_syms.get(symbol) replaced = key_repl is not None if key_repl is None: if keysym_to_mod(symbol): return False else: repl = event.string or symbol markup = GLib.markup_escape_text(repl) key_repl = KeyRepl(False, False, len(repl) > 1, markup) if event.modifiers['shift'] and \ (replaced or (mod != '' and \ self.vis_shift and \ self.mods_mode != 'emacs')): # add back shift for translated keys mod = mod + self.replace_mods['shift'] # Whitespace handling if not self.vis_space and mod == '' and symbol in WHITESPACE_SYMS: if symbol not in ['Return', 'KP_Enter']: repl = event.string elif self.multiline: repl = '' else: repl = key_repl.repl key_repl = KeyRepl(key_repl.bk_stop, key_repl.silent, key_repl.spaced, repl) # Multiline if symbol in ['Return', 'KP_Enter'] and self.multiline == True: key_repl = KeyRepl(key_repl.bk_stop, key_repl.silent, key_repl.spaced, key_repl.repl + '\n') if mod == '': if not self.mods_only: repl = key_repl.repl # switches if symbol in ['Caps_Lock', 'Num_Lock']: state = event.modifiers[symbol.lower()] repl += '(%s)' % (_('off') if state else _('on')) self.data.append(KeyData(datetime.now(), False, key_repl.bk_stop, key_repl.silent, key_repl.spaced, repl)) return True else: if self.mods_mode == 'emacs' or key_repl.repl[0] != mod[-1]: repl = mod + key_repl.repl else: repl = mod + '‟' + key_repl.repl + '”' self.data.append(KeyData(datetime.now(), True, key_repl.bk_stop, key_repl.silent, key_repl.spaced, repl)) return True return False def key_raw_mode(self, event): # modifiers mod = '' for cap in REPLACE_MODS.keys(): if event.modifiers[cap]: mod = mod + self.replace_mods[cap] # keycaps symbol = event.symbol.decode() key_repl = self.replace_syms.get(symbol) if key_repl is None: if keysym_to_mod(symbol): return False else: repl = event.string.upper() if event.string else symbol markup = GLib.markup_escape_text(repl) key_repl = KeyRepl(False, False, len(repl) > 1, markup) if mod == '': repl = key_repl.repl # switches if symbol in ['Caps_Lock', 'Num_Lock']: state = event.modifiers[symbol.lower()] repl += '(%s)' % (_('off') if state else _('on')) self.data.append(KeyData(datetime.now(), False, key_repl.bk_stop, key_repl.silent, key_repl.spaced, repl)) else: if self.mods_mode == 'emacs' or key_repl.repl[0] != mod[-1]: repl = mod + key_repl.repl else: repl = mod + '‟' + key_repl.repl + '”' self.data.append(KeyData(datetime.now(), True, key_repl.bk_stop, key_repl.silent, key_repl.spaced, repl)) return True def key_keysyms_mode(self, event): symbol = event.symbol.decode() if symbol in REPLACE_SYMS: value = symbol else: value = event.string or symbol self.data.append(KeyData(datetime.now(), True, True, True, True, value)) return True # callback for mouse button presses def btn_press(self, event): if not self.enabled: return False if event.pressed: action = "pressed" else: action = "released" self.logger.debug("Mouse button %d %s" % (event.btn, action)) # possible event.btn values: # 1 = LMB, 2 = MMB (wheel click), 3 = RMB, 4/5 = wheel up/down, # 6/7 = wheel left/right, 8+ extra buttons (e. g. thumb buttons) if event.btn > 7: # image_listener can only handle common buttons, redirect thumb buttons etc. to label if not event.pressed: return False # what we refer to as "Mouse 4" has an internal value of 8, # so we subtract 4 from the btn value markup = GLib.markup_escape_text("M{}".format(event.btn - 4)) # show as label, treated the same as keyboard button presses self.data.append(KeyData(datetime.now(), False, True, True, True, markup)) self.update_text() else: # show event in image self.image_listener( ButtonData(datetime.now(), event.btn, event.pressed) ) screenkey-v1.5/Screenkey/locale/000077500000000000000000000000001415444532700167355ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/ca/000077500000000000000000000000001415444532700173205ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/ca/LC_MESSAGES/000077500000000000000000000000001415444532700211055ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/ca/LC_MESSAGES/screenkey.po000066400000000000000000000341461415444532700234450ustar00rootroot00000000000000# Catalan translations for screenkey-i package. # Copyright (C) 2010 THE screenkey-i'S COPYRIGHT HOLDER # This file is distributed under the same license as the screenkey-i package. # Eduard Ereza Martínez , 2020. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-06-24 02:44+0200\n" "PO-Revision-Date: 2020-06-24 03:01+0200\n" "Last-Translator: Eduard Ereza Martínez \n" "Language-Team: Catalan\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.2.1\n" "Last-Translator: \n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "Language: ca\n" #: ../Screenkey/__init__.py:12 msgid "Screencast your keys" msgstr "Mostreu en pantalla les vostres tecles" #: ../Screenkey/__init__.py:22 msgid "Top" msgstr "A dalt" #: ../Screenkey/__init__.py:23 msgid "Center" msgstr "Al centre" #: ../Screenkey/__init__.py:24 msgid "Bottom" msgstr "A sota" #: ../Screenkey/__init__.py:25 msgid "Fixed" msgstr "Fixa" #: ../Screenkey/__init__.py:29 msgid "Large" msgstr "Grossa" #: ../Screenkey/__init__.py:30 msgid "Medium" msgstr "Mitjana" #: ../Screenkey/__init__.py:31 msgid "Small" msgstr "Petita" #: ../Screenkey/__init__.py:35 msgid "Composed" msgstr "Composat" #: ../Screenkey/__init__.py:36 msgid "Translated" msgstr "Traduït" #: ../Screenkey/__init__.py:37 msgid "Keysyms" msgstr "Símbols de tecles" #: ../Screenkey/__init__.py:38 msgid "Raw" msgstr "En brut" #: ../Screenkey/__init__.py:42 ../Screenkey/__init__.py:48 msgid "Normal" msgstr "Normal" #: ../Screenkey/__init__.py:43 msgid "Baked" msgstr "Incorporat" #: ../Screenkey/__init__.py:44 msgid "Full" msgstr "Complet" #: ../Screenkey/__init__.py:49 msgid "Emacs" msgstr "Emacs" #: ../Screenkey/__init__.py:50 msgid "Mac" msgstr "Mac" #: ../Screenkey/__init__.py:51 msgid "Windows" msgstr "Windows" #: ../Screenkey/__init__.py:52 msgid "Linux" msgstr "Linux" #: ../Screenkey/labelmanager.py:28 msgid "Esc" msgstr "Esc" #: ../Screenkey/labelmanager.py:29 ../Screenkey/labelmanager.py:30 msgid "↹" msgstr "↹" #: ../Screenkey/labelmanager.py:31 ../Screenkey/labelmanager.py:72 msgid "⏎" msgstr "⏎" #: ../Screenkey/labelmanager.py:32 msgid "␣" msgstr "␣" #: ../Screenkey/labelmanager.py:33 msgid "⌫" msgstr "⌫" #: ../Screenkey/labelmanager.py:34 msgid "Caps" msgstr "Bloq Maj" #: ../Screenkey/labelmanager.py:35 msgid "F1" msgstr "F1" #: ../Screenkey/labelmanager.py:36 msgid "F2" msgstr "F2" #: ../Screenkey/labelmanager.py:37 msgid "F3" msgstr "F3" #: ../Screenkey/labelmanager.py:38 msgid "F4" msgstr "F4" #: ../Screenkey/labelmanager.py:39 msgid "F5" msgstr "F5" #: ../Screenkey/labelmanager.py:40 msgid "F6" msgstr "F6" #: ../Screenkey/labelmanager.py:41 msgid "F7" msgstr "F7" #: ../Screenkey/labelmanager.py:42 msgid "F8" msgstr "F8" #: ../Screenkey/labelmanager.py:43 msgid "F9" msgstr "F9" #: ../Screenkey/labelmanager.py:44 msgid "F10" msgstr "F10" #: ../Screenkey/labelmanager.py:45 msgid "F11" msgstr "F11" #: ../Screenkey/labelmanager.py:46 msgid "F12" msgstr "F12" #: ../Screenkey/labelmanager.py:47 msgid "↑" msgstr "↑" #: ../Screenkey/labelmanager.py:48 msgid "←" msgstr "←" #: ../Screenkey/labelmanager.py:49 msgid "→" msgstr "→" #: ../Screenkey/labelmanager.py:50 msgid "↓" msgstr "↓" #: ../Screenkey/labelmanager.py:51 msgid "PgUp" msgstr "Re Pàg" #: ../Screenkey/labelmanager.py:52 msgid "PgDn" msgstr "Av Pàg" #: ../Screenkey/labelmanager.py:53 msgid "Home" msgstr "Inici" #: ../Screenkey/labelmanager.py:54 msgid "End" msgstr "Fi" #: ../Screenkey/labelmanager.py:55 msgid "Ins" msgstr "Inser" #: ../Screenkey/labelmanager.py:56 msgid "Del" msgstr "Supr" #: ../Screenkey/labelmanager.py:57 msgid "(1)" msgstr "(1)" #: ../Screenkey/labelmanager.py:58 msgid "(2)" msgstr "(2)" #: ../Screenkey/labelmanager.py:59 msgid "(3)" msgstr "(3)" #: ../Screenkey/labelmanager.py:60 msgid "(4)" msgstr "(4)" #: ../Screenkey/labelmanager.py:61 msgid "(5)" msgstr "(5)" #: ../Screenkey/labelmanager.py:62 msgid "(6)" msgstr "(6)" #: ../Screenkey/labelmanager.py:63 msgid "(7)" msgstr "(7)" #: ../Screenkey/labelmanager.py:64 msgid "(8)" msgstr "(8)" #: ../Screenkey/labelmanager.py:65 msgid "(9)" msgstr "(9)" #: ../Screenkey/labelmanager.py:66 msgid "(0)" msgstr "(0)" #: ../Screenkey/labelmanager.py:67 msgid "(.)" msgstr "(.)" #: ../Screenkey/labelmanager.py:68 msgid "(+)" msgstr "(+)" #: ../Screenkey/labelmanager.py:69 msgid "(-)" msgstr "(-)" #: ../Screenkey/labelmanager.py:70 msgid "(*)" msgstr "(*)" #: ../Screenkey/labelmanager.py:71 msgid "(/)" msgstr "(/)" #: ../Screenkey/labelmanager.py:73 msgid "NumLck" msgstr "Bloq Núm" #: ../Screenkey/labelmanager.py:74 msgid "ScrLck" msgstr "Bloq Despl" #: ../Screenkey/labelmanager.py:75 msgid "Pause" msgstr "Pausa" #: ../Screenkey/labelmanager.py:76 msgid "Break" msgstr "Interr" #: ../Screenkey/labelmanager.py:77 msgid "Print" msgstr "Impr Pant" #: ../Screenkey/labelmanager.py:78 msgid "Compose" msgstr "Redacta" #: ../Screenkey/labelmanager.py:81 ../Screenkey/labelmanager.py:82 msgid "\\uf026" msgstr "\\uf026" #: ../Screenkey/labelmanager.py:83 msgid "Mute" msgstr "Silencia" #: ../Screenkey/labelmanager.py:84 ../Screenkey/labelmanager.py:85 msgid "\\uf131" msgstr "\\uf131" #: ../Screenkey/labelmanager.py:86 msgid "Rec" msgstr "Enregistra" #: ../Screenkey/labelmanager.py:87 ../Screenkey/labelmanager.py:88 msgid "\\uf028" msgstr "\\uf028" #: ../Screenkey/labelmanager.py:89 ../Screenkey/labelmanager.py:92 msgid "Vol" msgstr "Volum" #: ../Screenkey/labelmanager.py:90 ../Screenkey/labelmanager.py:91 msgid "\\uf027" msgstr "\\uf027" #: ../Screenkey/labelmanager.py:93 ../Screenkey/labelmanager.py:94 msgid "\\uf048" msgstr "\\uf048" #: ../Screenkey/labelmanager.py:95 msgid "Prev" msgstr "Anterior" #: ../Screenkey/labelmanager.py:96 ../Screenkey/labelmanager.py:97 msgid "\\uf051" msgstr "\\uf051" #: ../Screenkey/labelmanager.py:98 msgid "Next" msgstr "Següent" #: ../Screenkey/labelmanager.py:99 ../Screenkey/labelmanager.py:100 msgid "\\uf04b" msgstr "\\uf04b" #: ../Screenkey/labelmanager.py:101 msgid "▶" msgstr "▶" #: ../Screenkey/labelmanager.py:102 ../Screenkey/labelmanager.py:103 msgid "\\uf04d" msgstr "\\uf04d" #: ../Screenkey/labelmanager.py:104 msgid "⬛" msgstr "⬛" #: ../Screenkey/labelmanager.py:105 ../Screenkey/labelmanager.py:106 msgid "\\uf052" msgstr "\\uf052" #: ../Screenkey/labelmanager.py:107 msgid "Eject" msgstr "Expulsa" #: ../Screenkey/labelmanager.py:108 ../Screenkey/labelmanager.py:109 #: ../Screenkey/labelmanager.py:111 ../Screenkey/labelmanager.py:112 msgid "\\uf185" msgstr "\\uf185" #: ../Screenkey/labelmanager.py:110 ../Screenkey/labelmanager.py:113 msgid "Bright" msgstr "Brillantor" #: ../Screenkey/labelmanager.py:114 ../Screenkey/labelmanager.py:115 msgid "\\uf108" msgstr "\\uf108" #: ../Screenkey/labelmanager.py:116 msgid "Display" msgstr "Pantalla" #: ../Screenkey/labelmanager.py:117 ../Screenkey/labelmanager.py:118 msgid "\\uf1eb" msgstr "\\uf1eb" #: ../Screenkey/labelmanager.py:119 msgid "WLAN" msgstr "Wi-Fi" #: ../Screenkey/labelmanager.py:120 ../Screenkey/labelmanager.py:121 msgid "\\uf002" msgstr "\\uf002" #: ../Screenkey/labelmanager.py:122 msgid "Search" msgstr "Cerca" #: ../Screenkey/labelmanager.py:123 ../Screenkey/labelmanager.py:124 msgid "\\uf294" msgstr "\\uf294" #: ../Screenkey/labelmanager.py:125 msgid "Bluetooth" msgstr "Bluetooth" #: ../Screenkey/labelmanager.py:126 msgid "\\uf7d9" msgstr "\\uf7d9" #: ../Screenkey/labelmanager.py:127 msgid "🛠" msgstr "🛠" #: ../Screenkey/labelmanager.py:128 ../Screenkey/labelmanager.py:129 msgid "\\uf005" msgstr "\\uf005" #: ../Screenkey/labelmanager.py:130 msgid "🟊" msgstr "🟊" #: ../Screenkey/labelmanager.py:145 msgid "Shift+" msgstr "Maj+" #: ../Screenkey/labelmanager.py:145 msgid "⇧+" msgstr "⇧+" #: ../Screenkey/labelmanager.py:146 msgid "Ctrl+" msgstr "Ctrl+" #: ../Screenkey/labelmanager.py:146 msgid "⌘+" msgstr "⌘+" #: ../Screenkey/labelmanager.py:147 msgid "Alt+" msgstr "Alt+" #: ../Screenkey/labelmanager.py:147 msgid "⌥+" msgstr "⌥+" #: ../Screenkey/labelmanager.py:148 msgid "Super+" msgstr "Súper+" #: ../Screenkey/labelmanager.py:149 ../Screenkey/labelmanager.py:150 msgid "\\uf17a" msgstr "\\uf17a" #: ../Screenkey/labelmanager.py:151 msgid "Win" msgstr "Windows" #: ../Screenkey/labelmanager.py:152 ../Screenkey/labelmanager.py:153 msgid "\\uf17c" msgstr "Bloq Maj\t" #: ../Screenkey/labelmanager.py:154 msgid "Super" msgstr "Súper" #: ../Screenkey/labelmanager.py:155 msgid "Hyper+" msgstr "Híper+" #: ../Screenkey/labelmanager.py:156 msgid "AltGr+" msgstr "Alt Gr+" #: ../Screenkey/labelmanager.py:432 ../Screenkey/labelmanager.py:473 msgid "off" msgstr "desactivat" #: ../Screenkey/labelmanager.py:432 ../Screenkey/labelmanager.py:473 msgid "on" msgstr "activat" #: ../Screenkey/screenkey.py:289 #, python-brace-format msgid "" "Screenkey failed to initialize. This is usually a sign of an improperly " "configured input method or desktop keyboard settings. Please see the troubleshooting documentation for further diagnosing " "instructions.\n" "\n" "Screenkey cannot recover and will now quit!" msgstr "" "No s'ha pogut inicialitzar l'Screenkey. Normalment, això indica que hi ha un " "mètode d'entrada mal configurat o una configuració errònia del teclat " "d'escriptori. Vegeu la documentació de solució de " "problemes per a més instruccions de diagnòstic.\n" "\n" "L'Screenkey no es pot recuperar i es tancarà." #: ../Screenkey/screenkey.py:475 #, python-brace-format msgid "" "\"slop\" is required for interactive selection. See {url}" msgstr "" "Cal l'\"slop\" per a la selecció interactiva. Vegeu {url}" #: ../Screenkey/screenkey.py:522 msgid "Time" msgstr "Temps" #: ../Screenkey/screenkey.py:530 msgid "Display for" msgstr "Mostra durant" #: ../Screenkey/screenkey.py:531 msgid "seconds" msgstr "segons" #: ../Screenkey/screenkey.py:544 msgid "Persistent window" msgstr "Finestra persistent" #: ../Screenkey/screenkey.py:551 ../Screenkey/screenkey.py:568 msgid "Position" msgstr "Posició" #: ../Screenkey/screenkey.py:559 msgid "Screen" msgstr "Pantalla" #: ../Screenkey/screenkey.py:577 msgid "Reset" msgstr "Reinicialitza" #: ../Screenkey/screenkey.py:585 msgid "Select window/region" msgstr "Selecciona una finestra/regió" #: ../Screenkey/screenkey.py:595 ../Screenkey/screenkey.py:605 msgid "Font" msgstr "Tipus de lletra" #: ../Screenkey/screenkey.py:614 msgid "Size" msgstr "Mida" #: ../Screenkey/screenkey.py:629 msgid "Keys" msgstr "Tecles" #: ../Screenkey/screenkey.py:637 msgid "Keyboard mode" msgstr "Mode de teclat" #: ../Screenkey/screenkey.py:646 msgid "Backspace mode" msgstr "Mode de retrocés" #: ../Screenkey/screenkey.py:655 msgid "Modifiers mode" msgstr "Mode de modificadors" #: ../Screenkey/screenkey.py:664 msgid "Show Modifier sequences only" msgstr "Mostra només les seqüències amb modificadors" #: ../Screenkey/screenkey.py:668 msgid "Always show Shift" msgstr "Mostra sempre Maj" #: ../Screenkey/screenkey.py:672 msgid "Show Whitespace characters" msgstr "Mostra els caràcters d'espai" #: ../Screenkey/screenkey.py:677 msgid "Compress repeats after" msgstr "Comprimeix les repeticions després de" #: ../Screenkey/screenkey.py:702 msgid "Color" msgstr "Color" #: ../Screenkey/screenkey.py:711 msgid "Font color" msgstr "Color de la lletra" #: ../Screenkey/screenkey.py:714 msgid "Text color" msgstr "Color del text" #: ../Screenkey/screenkey.py:718 ../Screenkey/screenkey.py:721 msgid "Background color" msgstr "Color de fons" #: ../Screenkey/screenkey.py:725 msgid "Opacity" msgstr "Opacitat" #: ../Screenkey/screenkey.py:759 msgid "Show keys" msgstr "Mostra les tecles" #: ../Screenkey/screenkey.py:765 msgid "Preferences" msgstr "Preferències" #: ../Screenkey/screenkey.py:770 msgid "About" msgstr "Quant a" #: ../Screenkey/screenkey.py:779 msgid "Quit" msgstr "Surt" #: ../screenkey:42 msgid "enable debugging" msgstr "activa la depuració" #: ../screenkey:44 msgid "do not create system tray icon" msgstr "no creïs una icona a la safata del sistema" #: ../screenkey:45 msgid "timeout in seconds" msgstr "temps màxim en segons" #: ../screenkey:47 msgid "set vertical position" msgstr "defineix la posició vertical" #: ../screenkey:49 msgid "make window persistent" msgstr "fes que la finestra sigui persistent" #: ../screenkey:51 msgid "set font size" msgstr "defineix la mida de la lletra" #: ../screenkey:53 msgid "set fixed area/window geometry" msgstr "defineix la geometria d'una àrea fixa/finestra" #: ../screenkey:55 msgid "set key processing mode" msgstr "defineix el mode de processament de tecles" #: ../screenkey:57 msgid "backspace processing mode" msgstr "mode de processament de retrocés" #: ../screenkey:59 msgid "modifiers visualization mode" msgstr "mode de visualització dels modificadors" #: ../screenkey:61 msgid "show only keys with modifiers pressed" msgstr "mostra només tecles amb modificadors premuts" #: ../screenkey:63 msgid "span text over multiple lines" msgstr "expandeix el text en múltiples línies" #: ../screenkey:65 msgid "always show Shift when modifiers are pressed" msgstr "mostra sempre Maj quan es premen els modificadors" #: ../screenkey:67 msgid "disable visualization of whitespace" msgstr "desactiva la visualització dels espais" #: ../screenkey:69 msgid "show settings dialog on start" msgstr "mostra el diàleg de configuració en iniciar" #: ../screenkey:71 msgid "show on the specified screen number" msgstr "mostra al número de pantalla indicat" #: ../screenkey:73 msgid "set font family/weight" msgstr "defineix el pes o la família de la lletra" #: ../screenkey:75 msgid "set font color" msgstr "defineix el color de la lletra" #: ../screenkey:77 msgid "background color" msgstr "color de fons" #: ../screenkey:79 msgid "window opacity (in range 0.0-1.0)" msgstr "opacitat de la finestra (en el rang 0.0-1.0)" #: ../screenkey:81 msgid "Ignore the specified KeySym" msgstr "Ignora el símbol de tecla especificat" #: ../screenkey:83 msgid "Compress key repeats after the specified count" msgstr "" "Comprimeix les repeticions de tecles després de la quantitat especificada" screenkey-v1.5/Screenkey/locale/de/000077500000000000000000000000001415444532700173255ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/de/LC_MESSAGES/000077500000000000000000000000001415444532700211125ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/de/LC_MESSAGES/screenkey.po000066400000000000000000000264761415444532700234610ustar00rootroot00000000000000# German (Germany) translations for screenkey. # Copyright (C) 2021 ORGANIZATION # This file is distributed under the same license as the screenkey project. # # FIRST AUTHOR , 2021. # Maik Schmalle , 2021. msgid "" msgstr "" "Project-Id-Version: screenkey 1.4\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2021-02-13 23:35+0100\n" "PO-Revision-Date: 2021-02-13 23:52+0100\n" "Last-Translator: Maik Schmalle \n" "Language: de_DE\n" "Language-Team: German \n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.9.0\n" #: Screenkey/__init__.py:17 msgid "Screencast your keys" msgstr "Screencast deine Tasten " #: Screenkey/__init__.py:27 msgid "Top" msgstr "Oben" #: Screenkey/__init__.py:28 msgid "Center" msgstr "Mitte" #: Screenkey/__init__.py:29 msgid "Bottom" msgstr "unten" #: Screenkey/__init__.py:30 msgid "Fixed" msgstr "Fest" #: Screenkey/__init__.py:34 msgid "Large" msgstr "Groß" #: Screenkey/__init__.py:35 msgid "Medium" msgstr "Mittel" #: Screenkey/__init__.py:36 msgid "Small" msgstr "schmal" #: Screenkey/__init__.py:40 msgid "Composed" msgstr "Composed" #: Screenkey/__init__.py:41 msgid "Translated" msgstr "Translated" #: Screenkey/__init__.py:42 msgid "Keysyms" msgstr "Keysyms" #: Screenkey/__init__.py:43 msgid "Raw" msgstr "Raw" #: Screenkey/__init__.py:47 Screenkey/__init__.py:53 msgid "Normal" msgstr "Normal" #: Screenkey/__init__.py:48 msgid "Baked" msgstr "Baked" #: Screenkey/__init__.py:49 msgid "Full" msgstr "Full" #: Screenkey/__init__.py:54 msgid "Emacs" msgstr "Emacs" #: Screenkey/__init__.py:55 msgid "Mac" msgstr "Mac" #: Screenkey/__init__.py:56 msgid "Windows" msgstr "Windows" #: Screenkey/__init__.py:57 msgid "Linux" msgstr "Linux" #: Screenkey/labelmanager.py:28 msgid "Esc" msgstr "Esc" #: Screenkey/labelmanager.py:29 Screenkey/labelmanager.py:30 msgid "↹" msgstr "↹" #: Screenkey/labelmanager.py:31 Screenkey/labelmanager.py:72 msgid "⏎" msgstr "⏎" #: Screenkey/labelmanager.py:32 msgid "␣" msgstr "␣" #: Screenkey/labelmanager.py:33 msgid "⌫" msgstr "⌫" #: Screenkey/labelmanager.py:34 msgid "Caps" msgstr "Umschalt" #: Screenkey/labelmanager.py:35 msgid "F1" msgstr "F1" #: Screenkey/labelmanager.py:36 msgid "F2" msgstr "F2" #: Screenkey/labelmanager.py:37 msgid "F3" msgstr "F3" #: Screenkey/labelmanager.py:38 msgid "F4" msgstr "F4" #: Screenkey/labelmanager.py:39 msgid "F5" msgstr "F5" #: Screenkey/labelmanager.py:40 msgid "F6" msgstr "F6" #: Screenkey/labelmanager.py:41 msgid "F7" msgstr "F7" #: Screenkey/labelmanager.py:42 msgid "F8" msgstr "F8" #: Screenkey/labelmanager.py:43 msgid "F9" msgstr "F9" #: Screenkey/labelmanager.py:44 msgid "F10" msgstr "F10" #: Screenkey/labelmanager.py:45 msgid "F11" msgstr "F11" #: Screenkey/labelmanager.py:46 msgid "F12" msgstr "F12" #: Screenkey/labelmanager.py:47 msgid "↑" msgstr "↑" #: Screenkey/labelmanager.py:48 msgid "←" msgstr "←" #: Screenkey/labelmanager.py:49 msgid "→" msgstr "→" #: Screenkey/labelmanager.py:50 msgid "↓" msgstr "↓" #: Screenkey/labelmanager.py:51 msgid "PgUp" msgstr "Bild↑" #: Screenkey/labelmanager.py:52 msgid "PgDn" msgstr "Bild↓" #: Screenkey/labelmanager.py:53 msgid "Home" msgstr "Pos1" #: Screenkey/labelmanager.py:54 msgid "End" msgstr "ende" #: Screenkey/labelmanager.py:55 msgid "Ins" msgstr "einfg" #: Screenkey/labelmanager.py:56 msgid "Del" msgstr "entf" #: Screenkey/labelmanager.py:57 msgid "(1)" msgstr "(1)" #: Screenkey/labelmanager.py:58 msgid "(2)" msgstr "(2)" #: Screenkey/labelmanager.py:59 msgid "(3)" msgstr "(3)" #: Screenkey/labelmanager.py:60 msgid "(4)" msgstr "(4)" #: Screenkey/labelmanager.py:61 msgid "(5)" msgstr "(5)" #: Screenkey/labelmanager.py:62 msgid "(6)" msgstr "(6)" #: Screenkey/labelmanager.py:63 msgid "(7)" msgstr "(7)" #: Screenkey/labelmanager.py:64 msgid "(8)" msgstr "(8)" #: Screenkey/labelmanager.py:65 msgid "(9)" msgstr "(9)" #: Screenkey/labelmanager.py:66 msgid "(0)" msgstr "(0)" #: Screenkey/labelmanager.py:67 msgid "(.)" msgstr "(.)" #: Screenkey/labelmanager.py:68 msgid "(+)" msgstr "(+)" #: Screenkey/labelmanager.py:69 msgid "(-)" msgstr "(-)" #: Screenkey/labelmanager.py:70 msgid "(*)" msgstr "(*)" #: Screenkey/labelmanager.py:71 msgid "(/)" msgstr "(/)" #: Screenkey/labelmanager.py:73 msgid "NumLck" msgstr "Num" #: Screenkey/labelmanager.py:74 msgid "ScrLck" msgstr "rollen" #: Screenkey/labelmanager.py:75 msgid "Pause" msgstr "Pause" #: Screenkey/labelmanager.py:76 msgid "Break" msgstr "Break" #: Screenkey/labelmanager.py:77 msgid "Print" msgstr "Drucken" #: Screenkey/labelmanager.py:78 msgid "Compose" msgstr "Compose" #: Screenkey/labelmanager.py:81 Screenkey/labelmanager.py:82 msgid "" msgstr "" #: Screenkey/labelmanager.py:83 msgid "Mute" msgstr "Mute" #: Screenkey/labelmanager.py:84 Screenkey/labelmanager.py:85 msgid "" msgstr "" #: Screenkey/labelmanager.py:86 msgid "Rec" msgstr "Rec" #: Screenkey/labelmanager.py:87 Screenkey/labelmanager.py:88 msgid "" msgstr "" #: Screenkey/labelmanager.py:89 Screenkey/labelmanager.py:92 msgid "Vol" msgstr "Vol" #: Screenkey/labelmanager.py:90 Screenkey/labelmanager.py:91 msgid "" msgstr "" #: Screenkey/labelmanager.py:93 Screenkey/labelmanager.py:94 msgid "" msgstr "" #: Screenkey/labelmanager.py:95 msgid "Prev" msgstr "voriger" #: Screenkey/labelmanager.py:96 Screenkey/labelmanager.py:97 msgid "" msgstr "" #: Screenkey/labelmanager.py:98 msgid "Next" msgstr "Nächser" #: Screenkey/labelmanager.py:99 Screenkey/labelmanager.py:100 msgid "" msgstr "" #: Screenkey/labelmanager.py:101 msgid "▶" msgstr "▶" #: Screenkey/labelmanager.py:102 Screenkey/labelmanager.py:103 msgid "" msgstr "" #: Screenkey/labelmanager.py:104 msgid "⬛" msgstr "⬛" #: Screenkey/labelmanager.py:105 Screenkey/labelmanager.py:106 msgid "" msgstr "" #: Screenkey/labelmanager.py:107 msgid "Eject" msgstr "Auswerfen" #: Screenkey/labelmanager.py:108 Screenkey/labelmanager.py:109 #: Screenkey/labelmanager.py:111 Screenkey/labelmanager.py:112 msgid "" msgstr "" #: Screenkey/labelmanager.py:110 Screenkey/labelmanager.py:113 msgid "Bright" msgstr "Hell" #: Screenkey/labelmanager.py:114 Screenkey/labelmanager.py:115 msgid "" msgstr "" #: Screenkey/labelmanager.py:116 msgid "Display" msgstr "Bildschirm" #: Screenkey/labelmanager.py:117 Screenkey/labelmanager.py:118 msgid "" msgstr "" #: Screenkey/labelmanager.py:119 msgid "WLAN" msgstr "WLAN" #: Screenkey/labelmanager.py:120 Screenkey/labelmanager.py:121 msgid "" msgstr "" #: Screenkey/labelmanager.py:122 msgid "Search" msgstr "Suchen" #: Screenkey/labelmanager.py:123 Screenkey/labelmanager.py:124 msgid "" msgstr "" #: Screenkey/labelmanager.py:125 msgid "Bluetooth" msgstr "Bluetooth" #: Screenkey/labelmanager.py:126 msgid "" msgstr "" #: Screenkey/labelmanager.py:127 msgid "🛠" msgstr "🛠" #: Screenkey/labelmanager.py:128 Screenkey/labelmanager.py:129 msgid "" msgstr "." #: Screenkey/labelmanager.py:130 msgid "🟊" msgstr "🟊" #: Screenkey/labelmanager.py:145 msgid "Shift+" msgstr "Umschalt+" #: Screenkey/labelmanager.py:145 msgid "⇧+" msgstr "⇧+" #: Screenkey/labelmanager.py:146 msgid "Ctrl+" msgstr "Strg+" #: Screenkey/labelmanager.py:146 msgid "⌘+" msgstr "⌘+" #: Screenkey/labelmanager.py:147 msgid "Alt+" msgstr "Alt+" #: Screenkey/labelmanager.py:147 msgid "⌥+" msgstr "⌥+" #: Screenkey/labelmanager.py:148 msgid "Super+" msgstr "Super+" #: Screenkey/labelmanager.py:149 Screenkey/labelmanager.py:150 msgid "" msgstr "" #: Screenkey/labelmanager.py:151 msgid "Win" msgstr "Win" #: Screenkey/labelmanager.py:152 Screenkey/labelmanager.py:153 msgid "" msgstr "" #: Screenkey/labelmanager.py:154 msgid "Super" msgstr "Super" #: Screenkey/labelmanager.py:155 msgid "Hyper+" msgstr "Hyper+" #: Screenkey/labelmanager.py:156 msgid "AltGr+" msgstr "AltGr+" #: Screenkey/labelmanager.py:452 Screenkey/labelmanager.py:493 msgid "off" msgstr "aus" #: Screenkey/labelmanager.py:452 Screenkey/labelmanager.py:493 msgid "on" msgstr "an" #: Screenkey/screenkey.py:418 msgid "" "Screenkey failed to initialize. This is usually a sign of an improperly " "configured input method or desktop keyboard settings. Please see the troubleshooting documentation for further diagnosing " "instructions.\n" "\n" "Screenkey cannot recover and will now quit!" msgstr "" "Screenkey konnte nicht initialisiert werden. Dies ist in der Regel ein " "Zeichen für eine unsachgemäßekonfigurierte Eingabemethode oder Desktop-" "Tastatureinstellungen. Bitte beachten Sie die " "Dokumentation zur Fehlerbehebung zur weiteren DiagnoseAnweisungen. " "\\ n\\ nScreenkey kann nicht wiederhergestellt werden und wird jetzt " "beendet!" #: Screenkey/screenkey.py:634 msgid "" "\"slop\" is required for interactive selection. See {url}" msgstr "" "\"Slop\" ist für die interaktive Auswahl erforderlich. Siehe {url} " #: Screenkey/screenkey.py:690 msgid "Time" msgstr "Zeit" #: Screenkey/screenkey.py:698 msgid "Display for" msgstr "Bildschirm" #: Screenkey/screenkey.py:699 Screenkey/screenkey.py:922 msgid "seconds" msgstr "Sekunden" #: Screenkey/screenkey.py:712 msgid "Persistent window" msgstr "Dauerhaftes Fenster" #: Screenkey/screenkey.py:719 Screenkey/screenkey.py:736 msgid "Position" msgstr "Position" #: Screenkey/screenkey.py:727 msgid "Screen" msgstr "Bildschirm" #: Screenkey/screenkey.py:745 msgid "Reset" msgstr "Neustart" #: Screenkey/screenkey.py:753 msgid "Select window/region" msgstr "Auswahl Fenster/Region" #: Screenkey/screenkey.py:763 Screenkey/screenkey.py:773 msgid "Font" msgstr "Schrift" #: Screenkey/screenkey.py:782 msgid "Size" msgstr "Größe" #: Screenkey/screenkey.py:797 msgid "Keys" msgstr "Taste" #: Screenkey/screenkey.py:805 msgid "Keyboard mode" msgstr "Tastatur Modus" #: Screenkey/screenkey.py:814 msgid "Backspace mode" msgstr "Rücktaste Modus" #: Screenkey/screenkey.py:823 msgid "Modifiers mode" msgstr "Modifikatormodus" #: Screenkey/screenkey.py:832 msgid "Show Modifier sequences only" msgstr "Nur Modifikatorsequenzen anzeigen" #: Screenkey/screenkey.py:836 msgid "Always show Shift" msgstr "Immer Umschalttaste zeigen" #: Screenkey/screenkey.py:840 msgid "Show Whitespace characters" msgstr "Leerzeichen anzeigen" #: Screenkey/screenkey.py:845 msgid "Compress repeats after" msgstr "Komprimieren Sie Wiederholungen nach" #: Screenkey/screenkey.py:870 msgid "Color" msgstr "Farbe" #: Screenkey/screenkey.py:879 msgid "Font color" msgstr "Schrift Farbe" #: Screenkey/screenkey.py:882 msgid "Text color" msgstr "Text Farbe" #: Screenkey/screenkey.py:886 Screenkey/screenkey.py:889 msgid "Background color" msgstr "Hintergrund Farbe" #: Screenkey/screenkey.py:893 msgid "Opacity" msgstr "Deckkraft" #: Screenkey/screenkey.py:908 msgid "Mouse" msgstr "Maus" #: Screenkey/screenkey.py:915 msgid "Show Mouse" msgstr "zeige Maus" #: Screenkey/screenkey.py:921 msgid "Hide duration" msgstr "ausblenden" #: Screenkey/screenkey.py:958 msgid "Show keys" msgstr "Zeige Tasten" #: Screenkey/screenkey.py:964 msgid "Preferences" msgstr "Einstellungen" #: Screenkey/screenkey.py:969 msgid "About" msgstr "Info" #: Screenkey/screenkey.py:978 msgid "Quit" msgstr "Beenden" screenkey-v1.5/Screenkey/locale/es/000077500000000000000000000000001415444532700173445ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/es/LC_MESSAGES/000077500000000000000000000000001415444532700211315ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/es/LC_MESSAGES/screenkey.po000066400000000000000000000040171415444532700234630ustar00rootroot00000000000000# Spanish translations for screenkey-i package. # Copyright (C) 2010 THE screenkey-i'S COPYRIGHT HOLDER # This file is distributed under the same license as the screenkey-i package. # Pablo Seminario , 2010. # msgid "" msgstr "" "Project-Id-Version: screenkey 0.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-15 16:22+0200\n" "PO-Revision-Date: 2010-06-15 16:27+0200\n" "Last-Translator: Pablo Seminario \n" "Language-Team: Spanish\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: screenkey:36 msgid "do not detach from the parent" msgstr "" #: screenkey:38 msgid "show debug information" msgstr "Muestra información de depuración" #: Screenkey/__init__.py:3 msgid "Screencast your keys" msgstr "Screencast tus teclas" #: Screenkey/screenkey.py:42 msgid "Top" msgstr "Superior" #: Screenkey/screenkey.py:43 msgid "Center" msgstr "Centro" #: Screenkey/screenkey.py:44 msgid "Bottom" msgstr "Inferior" #: Screenkey/screenkey.py:47 msgid "Large" msgstr "Grande" #: Screenkey/screenkey.py:48 msgid "Medium" msgstr "Mediano" #: Screenkey/screenkey.py:49 msgid "Small" msgstr "Pequeño" #: Screenkey/screenkey.py:52 msgid "Raw" msgstr "Crudo" #: Screenkey/screenkey.py:53 msgid "Normal" msgstr "Normal" #: Screenkey/screenkey.py:113 msgid "Show keys" msgstr "Mostar teclas" #: Screenkey/screenkey.py:295 msgid "Preferences" msgstr "Preferencias" #: Screenkey/screenkey.py:299 msgid "Time" msgstr "Tiempo" #: Screenkey/screenkey.py:304 msgid "Display for" msgstr "Mostrar durante" #: Screenkey/screenkey.py:305 msgid "seconds" msgstr "segundos" #: Screenkey/screenkey.py:322 msgid "Aspect" msgstr "Aspecto" #: Screenkey/screenkey.py:330 msgid "Position" msgstr "Posición" #: Screenkey/screenkey.py:345 msgid "Size" msgstr "Tamaño" #: Screenkey/screenkey.py:362 msgid "Keys" msgstr "Teclas" #: Screenkey/screenkey.py:367 msgid "Mode" msgstr "Modo" screenkey-v1.5/Screenkey/locale/fr/000077500000000000000000000000001415444532700173445ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/fr/LC_MESSAGES/000077500000000000000000000000001415444532700211315ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/fr/LC_MESSAGES/screenkey.po000066400000000000000000000261311415444532700234640ustar00rootroot00000000000000# French translations for screenkey-i package. # Copyright (C) 2010 THE screenkey-i'S COPYRIGHT HOLDER # This file is distributed under the same license as the screenkey-i package. # Pablo Seminario , 2010. # msgid "" msgstr "" "Project-Id-Version: screenkey 0.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-29 21:31+0100\n" "PO-Revision-Date: 2017-10-29 22:04+0100\n" "Last-Translator: Pablo Seminario \n" "Language-Team: French\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: ../screenkey:42 msgid "do not detach from the parent" msgstr "ne pas détacher du parent" #: ../screenkey:44 msgid "enable debugging (implies --no-detach)" msgstr "active le débogage (implique --no-detach)" #: ../screenkey:46 msgid "do not create system tray icon" msgstr "ne pas créer d'icône dans la barre système" #: ../screenkey:47 msgid "timeout in seconds" msgstr "délai maximal en secondes" #: ../screenkey:49 msgid "set vertical position" msgstr "réglage de la position verticale" #: ../screenkey:51 msgid "make window persistent" msgstr "rendre la fenêtre persistante" #: ../screenkey:53 msgid "set font size" msgstr "régler la taille de police" #: ../screenkey:55 msgid "set fixed area/window geometry" msgstr "régler la géométrique de zone fixe/fenêtre" #: ../screenkey:57 msgid "set key processing mode" msgstr "régler le mode de traitement des touches" #: ../screenkey:59 msgid "backspace processing mode" msgstr "mode de traitement de l'effacement arrière" #: ../screenkey:61 msgid "modifiers visualization mode" msgstr "mode de visualisation des modifieurs" #: ../screenkey:63 msgid "show only keys with modifiers pressed" msgstr "Ne montrer que les touches avec un modifieur pressé" #: ../screenkey:65 msgid "span text over multiple lines" msgstr "écrire le texte sur plusieurs lignes" #: ../screenkey:67 msgid "always show Shift when modifiers are pressed" msgstr "toujours montrer Maj quand les modifieurs sont pressés" #: ../screenkey:69 msgid "disable visualization of whitespace" msgstr "désactiver la visualisation de l'espace" #: ../screenkey:71 msgid "show settings dialog on start" msgstr "montrer le dialogue de réglages au démarrage" #: ../screenkey:73 msgid "show on the specified screen number" msgstr "montrer sur le numéro d'écran spécifié" #: ../screenkey:75 msgid "set font family/weight" msgstr "régler la famille de police/l'épaisseur" #: ../screenkey:77 msgid "set font color" msgstr "régler la couleur de la police" #: ../screenkey:79 msgid "background color" msgstr "couleur de fond" #: ../screenkey:81 msgid "window opacity (in range 0.0-1.0)" msgstr "opacité de la fenêtre (dans l'intervalle 0.0-1.0)" #: ../screenkey:83 msgid "Ignore the specified KeySym" msgstr "ignorer le KeySym spécifié" #: ../screenkey:85 msgid "Compress key repeats after the specified count" msgstr "Comprimer les répétitions de touches après le nombre spécifié" #: ../Screenkey/__init__.py:6 msgid "Screencast your keys" msgstr "Montre vos frappes à l'écran" #: ../Screenkey/__init__.py:12 msgid "Top" msgstr "Haut" #: ../Screenkey/__init__.py:13 msgid "Center" msgstr "Centre" #: ../Screenkey/__init__.py:14 msgid "Bottom" msgstr "Bas" #: ../Screenkey/__init__.py:15 msgid "Fixed" msgstr "Fixe" #: ../Screenkey/__init__.py:19 msgid "Large" msgstr "Grand" #: ../Screenkey/__init__.py:20 msgid "Medium" msgstr "Moyen" #: ../Screenkey/__init__.py:21 msgid "Small" msgstr "Petit" #: ../Screenkey/__init__.py:25 msgid "Composed" msgstr "Composé" #: ../Screenkey/__init__.py:26 msgid "Translated" msgstr "Traduit" #: ../Screenkey/__init__.py:27 msgid "Keysyms" msgstr "Keysyms" #: ../Screenkey/__init__.py:28 msgid "Raw" msgstr "Brut" #: ../Screenkey/__init__.py:32 ../Screenkey/__init__.py:38 msgid "Normal" msgstr "Normal" #: ../Screenkey/__init__.py:33 msgid "Baked" msgstr "Tout cuit" #: ../Screenkey/__init__.py:34 msgid "Full" msgstr "Complet" #: ../Screenkey/__init__.py:39 msgid "Emacs" msgstr "Emacs" #: ../Screenkey/__init__.py:40 msgid "Mac" msgstr "Mac" #: ../Screenkey/screenkey.py:451 msgid "Preferences" msgstr "Préférences" #: ../Screenkey/screenkey.py:454 msgid "Time" msgstr "Temps" #: ../Screenkey/screenkey.py:460 msgid "Display for" msgstr "Affichage pour" #: ../Screenkey/screenkey.py:461 msgid "seconds" msgstr "secondes" #: ../Screenkey/screenkey.py:474 msgid "Persistent window" msgstr "Fenêtre persistante" #: ../Screenkey/screenkey.py:482 ../Screenkey/screenkey.py:501 msgid "Position" msgstr "Position" #: ../Screenkey/screenkey.py:488 msgid "Screen" msgstr "Écran" #: ../Screenkey/screenkey.py:509 msgid "Reset" msgstr "Redémarrer" #: ../Screenkey/screenkey.py:519 msgid "Select window/region" msgstr "Sélectionner la fenêtre/région" #: ../Screenkey/screenkey.py:523 msgid "Aspect" msgstr "Aspect" #: ../Screenkey/screenkey.py:532 msgid "Font" msgstr "Police" #: ../Screenkey/screenkey.py:542 msgid "Size" msgstr "Taille" #: ../Screenkey/screenkey.py:555 msgid "Font color" msgstr "Couleur de police" #: ../Screenkey/screenkey.py:567 msgid "Opacity" msgstr "Opacité" #: ../Screenkey/screenkey.py:582 msgid "Keys" msgstr "Touches" #: ../Screenkey/screenkey.py:589 msgid "Keyboard mode" msgstr "Mode du clavier" #: ../Screenkey/screenkey.py:601 msgid "Backspace mode" msgstr "Mode de l'effacement arrière" #: ../Screenkey/screenkey.py:612 msgid "Modifiers mode" msgstr "Mode des modifieurs" #: ../Screenkey/screenkey.py:622 msgid "Show Modifier sequences only" msgstr "Montrer seulement les séquences de modifieurs" #: ../Screenkey/screenkey.py:627 msgid "Always show Shift" msgstr "Toujours montrer Maj" #: ../Screenkey/screenkey.py:632 msgid "Show Whitespace characters" msgstr "Montrer les caractères d'espacement" #: ../Screenkey/screenkey.py:638 msgid "Compress repeats after" msgstr "Comprimer les répétitions après" #: ../Screenkey/screenkey.py:676 msgid "Show keys" msgstr "Montrer les touches" #. Regular keys #: ../Screenkey/labelmanager.py:28 msgid "Esc" msgstr "Échap" #: ../Screenkey/labelmanager.py:29 msgid "↹" msgstr "↹" #: ../Screenkey/labelmanager.py:30 ../Screenkey/labelmanager.py:71 msgid "⏎" msgstr "⏎" #: ../Screenkey/labelmanager.py:31 msgid "␣" msgstr "␣" #: ../Screenkey/labelmanager.py:32 msgid "⌫" msgstr "⌫" #: ../Screenkey/labelmanager.py:33 msgid "Caps" msgstr "Verr.Maj" #: ../Screenkey/labelmanager.py:34 msgid "F1" msgstr "F1" #: ../Screenkey/labelmanager.py:35 msgid "F2" msgstr "F2" #: ../Screenkey/labelmanager.py:36 msgid "F3" msgstr "F3" #: ../Screenkey/labelmanager.py:37 msgid "F4" msgstr "F4" #: ../Screenkey/labelmanager.py:38 msgid "F5" msgstr "F5" #: ../Screenkey/labelmanager.py:39 msgid "F6" msgstr "F6" #: ../Screenkey/labelmanager.py:40 msgid "F7" msgstr "F7" #: ../Screenkey/labelmanager.py:41 msgid "F8" msgstr "F8" #: ../Screenkey/labelmanager.py:42 msgid "F9" msgstr "F9" #: ../Screenkey/labelmanager.py:43 msgid "F10" msgstr "F10" #: ../Screenkey/labelmanager.py:44 msgid "F11" msgstr "F11" #: ../Screenkey/labelmanager.py:45 msgid "F12" msgstr "F12" #: ../Screenkey/labelmanager.py:46 msgid "↑" msgstr "↑" #: ../Screenkey/labelmanager.py:47 msgid "←" msgstr "←" #: ../Screenkey/labelmanager.py:48 msgid "→" msgstr "→" #: ../Screenkey/labelmanager.py:49 msgid "↓" msgstr "↓" #: ../Screenkey/labelmanager.py:50 msgid "PgUp" msgstr "PgHaut" #: ../Screenkey/labelmanager.py:51 msgid "PgDn" msgstr "PgBas" #: ../Screenkey/labelmanager.py:52 msgid "Home" msgstr "Début" #: ../Screenkey/labelmanager.py:53 msgid "End" msgstr "Fin" #: ../Screenkey/labelmanager.py:54 msgid "Ins" msgstr "Ins" #: ../Screenkey/labelmanager.py:55 msgid "Del" msgstr "Suppr" #: ../Screenkey/labelmanager.py:56 msgid "(1)" msgstr "(1)" #: ../Screenkey/labelmanager.py:57 msgid "(2)" msgstr "(2)" #: ../Screenkey/labelmanager.py:58 msgid "(3)" msgstr "(3)" #: ../Screenkey/labelmanager.py:59 msgid "(4)" msgstr "(4)" #: ../Screenkey/labelmanager.py:60 msgid "(5)" msgstr "(5)" #: ../Screenkey/labelmanager.py:61 msgid "(6)" msgstr "(6)" #: ../Screenkey/labelmanager.py:62 msgid "(7)" msgstr "(7)" #: ../Screenkey/labelmanager.py:63 msgid "(8)" msgstr "(8)" #: ../Screenkey/labelmanager.py:64 msgid "(9)" msgstr "(9)" #: ../Screenkey/labelmanager.py:65 msgid "(0)" msgstr "(0)" #: ../Screenkey/labelmanager.py:66 msgid "(.)" msgstr "(.)" #: ../Screenkey/labelmanager.py:67 msgid "(+)" msgstr "(+)" #: ../Screenkey/labelmanager.py:68 msgid "(-)" msgstr "(-)" #: ../Screenkey/labelmanager.py:69 msgid "(*)" msgstr "(*)" #: ../Screenkey/labelmanager.py:70 msgid "(/)" msgstr "(/)" #: ../Screenkey/labelmanager.py:72 msgid "NumLck" msgstr "Verr.Num" #: ../Screenkey/labelmanager.py:73 msgid "ScrLck" msgstr "Verr.Écran" #: ../Screenkey/labelmanager.py:74 msgid "Pause" msgstr "Pause" #: ../Screenkey/labelmanager.py:75 msgid "Break" msgstr "Break" #: ../Screenkey/labelmanager.py:76 msgid "Print" msgstr "Impr.Écran" #: ../Screenkey/labelmanager.py:77 msgid "Compose" msgstr "Compose" #. Multimedia keys #: ../Screenkey/labelmanager.py:80 msgid "\\uf026" msgstr "" #: ../Screenkey/labelmanager.py:81 msgid "Mute" msgstr "Mute" #: ../Screenkey/labelmanager.py:82 msgid "\\uf131" msgstr "" #: ../Screenkey/labelmanager.py:83 msgid "Rec" msgstr "Enr" #: ../Screenkey/labelmanager.py:84 msgid "\\uf028" msgstr "" #: ../Screenkey/labelmanager.py:85 msgid "Vol+" msgstr "Vol+" #: ../Screenkey/labelmanager.py:86 msgid "\\uf027" msgstr "" #: ../Screenkey/labelmanager.py:87 msgid "Vol-" msgstr "Vol-" #: ../Screenkey/labelmanager.py:88 msgid "\\uf186" msgstr "" #: ../Screenkey/labelmanager.py:89 msgid "Bright+" msgstr "Lum+" #: ../Screenkey/labelmanager.py:90 msgid "\\uf185" msgstr "" #: ../Screenkey/labelmanager.py:91 msgid "Bright-" msgstr "Lum-" #: ../Screenkey/labelmanager.py:92 msgid "\\uf108" msgstr "" #: ../Screenkey/labelmanager.py:93 msgid "Display" msgstr "Affichage" #: ../Screenkey/labelmanager.py:94 msgid "\\uf1eb" msgstr "" #: ../Screenkey/labelmanager.py:95 msgid "WLAN" msgstr "WIFI" #: ../Screenkey/labelmanager.py:96 msgid "\\uf002" msgstr "" #: ../Screenkey/labelmanager.py:97 msgid "Search" msgstr "Recherche" #: ../Screenkey/labelmanager.py:118 msgid "Shift+" msgstr "Maj+" #: ../Screenkey/labelmanager.py:118 msgid "⇧+" msgstr "⇧+" #: ../Screenkey/labelmanager.py:119 msgid "Ctrl+" msgstr "Ctrl+" #: ../Screenkey/labelmanager.py:119 msgid "⌘+" msgstr "⌘+" #: ../Screenkey/labelmanager.py:120 msgid "Alt+" msgstr "Alt+" #: ../Screenkey/labelmanager.py:120 msgid "⌥+" msgstr "⌥+" #: ../Screenkey/labelmanager.py:121 msgid "Super+" msgstr "Super+" #: ../Screenkey/labelmanager.py:122 msgid "Hyper+" msgstr "Hyper+" #: ../Screenkey/labelmanager.py:123 msgid "AltGr+" msgstr "AltGr+" #: ../Screenkey/labelmanager.py:369 ../Screenkey/labelmanager.py:409 msgid "off" msgstr "off" #: ../Screenkey/labelmanager.py:369 ../Screenkey/labelmanager.py:409 msgid "on" msgstr "on" #~ msgid "show debug information" #~ msgstr "montrer l'information de débogage" #~ msgid "Time" #~ msgstr "Temps" #~ msgid "Keys" #~ msgstr "Touches" #~ msgid "Mode" #~ msgstr "Mode" screenkey-v1.5/Screenkey/locale/ru/000077500000000000000000000000001415444532700173635ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/ru/LC_MESSAGES/000077500000000000000000000000001415444532700211505ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/ru/LC_MESSAGES/screenkey.po000066400000000000000000000372571415444532700235160ustar00rootroot00000000000000# Russian translation for screenkey # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # FIRST AUTHOR , 2020. # Olesya Gerasimenko , 2020. msgid "" msgstr "" "Project-Id-Version: screenkey\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-06-24 02:44+0200\n" "PO-Revision-Date: 2020-07-28 17:16+0300\n" "Last-Translator: Olesya Gerasimenko \n" "Language-Team: Basealt Translation Team\n" "Language: ru_RU\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<" "=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Lokalize 19.12.3\n" #: ../Screenkey/__init__.py:12 msgid "Screencast your keys" msgstr "Показать клавиши на экране" #: ../Screenkey/__init__.py:22 msgid "Top" msgstr "Вверху" #: ../Screenkey/__init__.py:23 msgid "Center" msgstr "По центру" #: ../Screenkey/__init__.py:24 msgid "Bottom" msgstr "Внизу" #: ../Screenkey/__init__.py:25 msgid "Fixed" msgstr "Фиксированный" #: ../Screenkey/__init__.py:29 msgid "Large" msgstr "Крупный" #: ../Screenkey/__init__.py:30 msgid "Medium" msgstr "Средний" #: ../Screenkey/__init__.py:31 msgid "Small" msgstr "Малый" #: ../Screenkey/__init__.py:35 msgid "Composed" msgstr "Скомпонованный" #: ../Screenkey/__init__.py:36 msgid "Translated" msgstr "Переведённый" #: ../Screenkey/__init__.py:37 msgid "Keysyms" msgstr "Символы" #: ../Screenkey/__init__.py:38 msgid "Raw" msgstr "Необработанный" #: ../Screenkey/__init__.py:42 ../Screenkey/__init__.py:48 msgid "Normal" msgstr "Нормальный" #: ../Screenkey/__init__.py:43 msgid "Baked" msgstr "Встроенный" #: ../Screenkey/__init__.py:44 msgid "Full" msgstr "Полный" #: ../Screenkey/__init__.py:49 msgid "Emacs" msgstr "Emacs" #: ../Screenkey/__init__.py:50 msgid "Mac" msgstr "Mac" #: ../Screenkey/__init__.py:51 msgid "Windows" msgstr "Windows" #: ../Screenkey/__init__.py:52 msgid "Linux" msgstr "Linux" #: ../Screenkey/labelmanager.py:28 msgid "Esc" msgstr "Esc" #: ../Screenkey/labelmanager.py:29 ../Screenkey/labelmanager.py:30 msgid "↹" msgstr "↹" #: ../Screenkey/labelmanager.py:31 ../Screenkey/labelmanager.py:72 msgid "⏎" msgstr "⏎" #: ../Screenkey/labelmanager.py:32 msgid "␣" msgstr "␣" #: ../Screenkey/labelmanager.py:33 msgid "⌫" msgstr "⌫" #: ../Screenkey/labelmanager.py:34 msgid "Caps" msgstr "Прописные" #: ../Screenkey/labelmanager.py:35 msgid "F1" msgstr "F1" #: ../Screenkey/labelmanager.py:36 msgid "F2" msgstr "F2" #: ../Screenkey/labelmanager.py:37 msgid "F3" msgstr "F3" #: ../Screenkey/labelmanager.py:38 msgid "F4" msgstr "F4" #: ../Screenkey/labelmanager.py:39 msgid "F5" msgstr "F5" #: ../Screenkey/labelmanager.py:40 msgid "F6" msgstr "F6" #: ../Screenkey/labelmanager.py:41 msgid "F7" msgstr "F7" #: ../Screenkey/labelmanager.py:42 msgid "F8" msgstr "F8" #: ../Screenkey/labelmanager.py:43 msgid "F9" msgstr "F9" #: ../Screenkey/labelmanager.py:44 msgid "F10" msgstr "F10" #: ../Screenkey/labelmanager.py:45 msgid "F11" msgstr "F11" #: ../Screenkey/labelmanager.py:46 msgid "F12" msgstr "F12" #: ../Screenkey/labelmanager.py:47 msgid "↑" msgstr "↑" #: ../Screenkey/labelmanager.py:48 msgid "←" msgstr "←" #: ../Screenkey/labelmanager.py:49 msgid "→" msgstr "→" #: ../Screenkey/labelmanager.py:50 msgid "↓" msgstr "↓" #: ../Screenkey/labelmanager.py:51 msgid "PgUp" msgstr "Стр. вверх" #: ../Screenkey/labelmanager.py:52 msgid "PgDn" msgstr "Стр. вниз" #: ../Screenkey/labelmanager.py:53 msgid "Home" msgstr "Домой" #: ../Screenkey/labelmanager.py:54 msgid "End" msgstr "В конец" #: ../Screenkey/labelmanager.py:55 msgid "Ins" msgstr "Вставить" #: ../Screenkey/labelmanager.py:56 msgid "Del" msgstr "Удалить" #: ../Screenkey/labelmanager.py:57 msgid "(1)" msgstr "(1)" #: ../Screenkey/labelmanager.py:58 msgid "(2)" msgstr "(2)" #: ../Screenkey/labelmanager.py:59 msgid "(3)" msgstr "(3)" #: ../Screenkey/labelmanager.py:60 msgid "(4)" msgstr "(4)" #: ../Screenkey/labelmanager.py:61 msgid "(5)" msgstr "(5)" #: ../Screenkey/labelmanager.py:62 msgid "(6)" msgstr "(6)" #: ../Screenkey/labelmanager.py:63 msgid "(7)" msgstr "(7)" #: ../Screenkey/labelmanager.py:64 msgid "(8)" msgstr "(8)" #: ../Screenkey/labelmanager.py:65 msgid "(9)" msgstr "(9)" #: ../Screenkey/labelmanager.py:66 msgid "(0)" msgstr "(0)" #: ../Screenkey/labelmanager.py:67 msgid "(.)" msgstr "(.)" #: ../Screenkey/labelmanager.py:68 msgid "(+)" msgstr "(+)" #: ../Screenkey/labelmanager.py:69 msgid "(-)" msgstr "(-)" #: ../Screenkey/labelmanager.py:70 msgid "(*)" msgstr "(*)" #: ../Screenkey/labelmanager.py:71 msgid "(/)" msgstr "(/)" #: ../Screenkey/labelmanager.py:73 msgid "NumLck" msgstr "Зафикс. цифры" #: ../Screenkey/labelmanager.py:74 msgid "ScrLck" msgstr "Зафикс. прокрутку" #: ../Screenkey/labelmanager.py:75 msgid "Pause" msgstr "Приостановить" #: ../Screenkey/labelmanager.py:76 msgid "Break" msgstr "Прервать" #: ../Screenkey/labelmanager.py:77 msgid "Print" msgstr "Печать" #: ../Screenkey/labelmanager.py:78 msgid "Compose" msgstr "Набрать" #: ../Screenkey/labelmanager.py:81 ../Screenkey/labelmanager.py:82 msgid "\\uf026" msgstr "\\uf026" #: ../Screenkey/labelmanager.py:83 msgid "Mute" msgstr "Отключить звук" #: ../Screenkey/labelmanager.py:84 ../Screenkey/labelmanager.py:85 msgid "\\uf131" msgstr "\\uf131" #: ../Screenkey/labelmanager.py:86 msgid "Rec" msgstr "Записать" #: ../Screenkey/labelmanager.py:87 ../Screenkey/labelmanager.py:88 msgid "\\uf028" msgstr "\\uf028" #: ../Screenkey/labelmanager.py:89 ../Screenkey/labelmanager.py:92 msgid "Vol" msgstr "Громкость" #: ../Screenkey/labelmanager.py:90 ../Screenkey/labelmanager.py:91 msgid "\\uf027" msgstr "\\uf027" #: ../Screenkey/labelmanager.py:93 ../Screenkey/labelmanager.py:94 msgid "\\uf048" msgstr "\\uf048" #: ../Screenkey/labelmanager.py:95 msgid "Prev" msgstr "Пред." #: ../Screenkey/labelmanager.py:96 ../Screenkey/labelmanager.py:97 msgid "\\uf051" msgstr "\\uf051" #: ../Screenkey/labelmanager.py:98 msgid "Next" msgstr "След." #: ../Screenkey/labelmanager.py:99 ../Screenkey/labelmanager.py:100 msgid "\\uf04b" msgstr "\\uf04b" #: ../Screenkey/labelmanager.py:101 msgid "▶" msgstr "▶" #: ../Screenkey/labelmanager.py:102 ../Screenkey/labelmanager.py:103 msgid "\\uf04d" msgstr "\\uf04d" #: ../Screenkey/labelmanager.py:104 msgid "⬛" msgstr "⬛" #: ../Screenkey/labelmanager.py:105 ../Screenkey/labelmanager.py:106 msgid "\\uf052" msgstr "\\uf052" #: ../Screenkey/labelmanager.py:107 msgid "Eject" msgstr "Извлечь" #: ../Screenkey/labelmanager.py:108 ../Screenkey/labelmanager.py:109 #: ../Screenkey/labelmanager.py:111 ../Screenkey/labelmanager.py:112 msgid "\\uf185" msgstr "\\uf185" #: ../Screenkey/labelmanager.py:110 ../Screenkey/labelmanager.py:113 msgid "Bright" msgstr "Яркость" #: ../Screenkey/labelmanager.py:114 ../Screenkey/labelmanager.py:115 msgid "\\uf108" msgstr "\\uf108" #: ../Screenkey/labelmanager.py:116 msgid "Display" msgstr "Экран" #: ../Screenkey/labelmanager.py:117 ../Screenkey/labelmanager.py:118 msgid "\\uf1eb" msgstr "\\uf1eb" #: ../Screenkey/labelmanager.py:119 msgid "WLAN" msgstr "Wi-Fi" #: ../Screenkey/labelmanager.py:120 ../Screenkey/labelmanager.py:121 msgid "\\uf002" msgstr "\\uf002" #: ../Screenkey/labelmanager.py:122 msgid "Search" msgstr "Найти" #: ../Screenkey/labelmanager.py:123 ../Screenkey/labelmanager.py:124 msgid "\\uf294" msgstr "\\uf294" #: ../Screenkey/labelmanager.py:125 msgid "Bluetooth" msgstr "Bluetooth" #: ../Screenkey/labelmanager.py:126 msgid "\\uf7d9" msgstr "\\uf7d9" #: ../Screenkey/labelmanager.py:127 msgid "🛠" msgstr "🛠" #: ../Screenkey/labelmanager.py:128 ../Screenkey/labelmanager.py:129 msgid "\\uf005" msgstr "\\uf005" #: ../Screenkey/labelmanager.py:130 msgid "🟊" msgstr "🟊" #: ../Screenkey/labelmanager.py:145 msgid "Shift+" msgstr "Shift+" #: ../Screenkey/labelmanager.py:145 msgid "⇧+" msgstr "⇧+" #: ../Screenkey/labelmanager.py:146 msgid "Ctrl+" msgstr "Ctrl+" #: ../Screenkey/labelmanager.py:146 msgid "⌘+" msgstr "⌘+" #: ../Screenkey/labelmanager.py:147 msgid "Alt+" msgstr "Alt+" #: ../Screenkey/labelmanager.py:147 msgid "⌥+" msgstr "⌥+" #: ../Screenkey/labelmanager.py:148 msgid "Super+" msgstr "Super+" #: ../Screenkey/labelmanager.py:149 ../Screenkey/labelmanager.py:150 msgid "\\uf17a" msgstr "\\uf17a" #: ../Screenkey/labelmanager.py:151 msgid "Win" msgstr "Windows" #: ../Screenkey/labelmanager.py:152 ../Screenkey/labelmanager.py:153 msgid "\\uf17c" msgstr "\\uf17c" #: ../Screenkey/labelmanager.py:154 msgid "Super" msgstr "Super" #: ../Screenkey/labelmanager.py:155 msgid "Hyper+" msgstr "Hyper+" #: ../Screenkey/labelmanager.py:156 msgid "AltGr+" msgstr "Alt Graph+" #: ../Screenkey/labelmanager.py:432 ../Screenkey/labelmanager.py:473 msgid "off" msgstr "выкл." #: ../Screenkey/labelmanager.py:432 ../Screenkey/labelmanager.py:473 msgid "on" msgstr "вкл." #: ../Screenkey/screenkey.py:289 #, python-brace-format msgid "" "Screenkey failed to initialize. This is usually a sign of an improperly " "configured input method or desktop keyboard settings. Please see the troubleshooting documentation for further diagnosing " "instructions.\n" "\n" "Screenkey cannot recover and will now quit!" msgstr "" "Не удалось инициализировать Screenkey. Обычно это указывает на неверную" " конфигурацию метода ввода или параметров настольной клавиатуры. Более" " подробные сведения о диагностике доступны в документации" " по устранению ошибок.\n" "\n" "Сейчас будет выполнен выход из программы Screenkey!" #: ../Screenkey/screenkey.py:475 #, python-brace-format msgid "" "\"slop\" is required for interactive selection. See {url}" msgstr "" "Для интерактивного выделения требуется «slop». Подробнее: {url}" #: ../Screenkey/screenkey.py:522 msgid "Time" msgstr "Время" #: ../Screenkey/screenkey.py:530 msgid "Display for" msgstr "Показывать в течение" #: ../Screenkey/screenkey.py:531 msgid "seconds" msgstr "секунд" #: ../Screenkey/screenkey.py:544 msgid "Persistent window" msgstr "Основное окно" #: ../Screenkey/screenkey.py:551 ../Screenkey/screenkey.py:568 msgid "Position" msgstr "Расположение" #: ../Screenkey/screenkey.py:559 msgid "Screen" msgstr "Экран" #: ../Screenkey/screenkey.py:577 msgid "Reset" msgstr "Сброс" #: ../Screenkey/screenkey.py:585 msgid "Select window/region" msgstr "Выберите окно/область экрана" #: ../Screenkey/screenkey.py:595 ../Screenkey/screenkey.py:605 msgid "Font" msgstr "Шрифт" #: ../Screenkey/screenkey.py:614 msgid "Size" msgstr "Размер" #: ../Screenkey/screenkey.py:629 msgid "Keys" msgstr "Клавиши" #: ../Screenkey/screenkey.py:637 msgid "Keyboard mode" msgstr "Режим клавиатуры" #: ../Screenkey/screenkey.py:646 msgid "Backspace mode" msgstr "Режим Backspace" #: ../Screenkey/screenkey.py:655 msgid "Modifiers mode" msgstr "Режим модификаторов" #: ../Screenkey/screenkey.py:664 msgid "Show Modifier sequences only" msgstr "Показывать только последовательность модификаторов" #: ../Screenkey/screenkey.py:668 msgid "Always show Shift" msgstr "Всегда показывать нажатие Shift" #: ../Screenkey/screenkey.py:672 msgid "Show Whitespace characters" msgstr "Показывать пробелы" #: ../Screenkey/screenkey.py:677 msgid "Compress repeats after" msgstr "Сокращать повторы после" #: ../Screenkey/screenkey.py:702 msgid "Color" msgstr "Цвет" #: ../Screenkey/screenkey.py:711 msgid "Font color" msgstr "Цвет шрифта" #: ../Screenkey/screenkey.py:714 msgid "Text color" msgstr "Цвет текста" #: ../Screenkey/screenkey.py:718 ../Screenkey/screenkey.py:721 msgid "Background color" msgstr "Цвет фона" #: ../Screenkey/screenkey.py:725 msgid "Opacity" msgstr "Прозрачность" #: ../Screenkey/screenkey.py:759 msgid "Show keys" msgstr "Показать клавиши" #: ../Screenkey/screenkey.py:765 msgid "Preferences" msgstr "Параметры" #: ../Screenkey/screenkey.py:770 msgid "About" msgstr "О программе" #: ../Screenkey/screenkey.py:779 msgid "Quit" msgstr "Выход" #: ../screenkey:42 msgid "enable debugging" msgstr "включить отладку" #: ../screenkey:44 msgid "do not create system tray icon" msgstr "не создавать значок в системном лотке" #: ../screenkey:45 msgid "timeout in seconds" msgstr "время ожидания (сек.)" #: ../screenkey:47 msgid "set vertical position" msgstr "установить вертикальное расположение" #: ../screenkey:49 msgid "make window persistent" msgstr "сделать окно основным" #: ../screenkey:51 msgid "set font size" msgstr "указать размер шрифта" #: ../screenkey:53 msgid "set fixed area/window geometry" msgstr "указать геометрию фиксированной области/окна" #: ../screenkey:55 msgid "set key processing mode" msgstr "указать режим обработки клавиш" #: ../screenkey:57 msgid "backspace processing mode" msgstr "режим обработки Backspace" #: ../screenkey:59 msgid "modifiers visualization mode" msgstr "режим отображения модификаторов" #: ../screenkey:61 msgid "show only keys with modifiers pressed" msgstr "показывать только клавиши с нажатыми модификаторами" #: ../screenkey:63 msgid "span text over multiple lines" msgstr "размещать текст на нескольких строках" #: ../screenkey:65 msgid "always show Shift when modifiers are pressed" msgstr "всегда показывать Shift при нажатии модификаторов" #: ../screenkey:67 msgid "disable visualization of whitespace" msgstr "отключить отображение пробелов" #: ../screenkey:69 msgid "show settings dialog on start" msgstr "показывать диалог настройки параметров при запуске" #: ../screenkey:71 msgid "show on the specified screen number" msgstr "показывать на экране с указанным номером" #: ../screenkey:73 msgid "set font family/weight" msgstr "указать семейство/вес шрифта" #: ../screenkey:75 msgid "set font color" msgstr "указать цвет шрифта" #: ../screenkey:77 msgid "background color" msgstr "цвет фона" #: ../screenkey:79 msgid "window opacity (in range 0.0-1.0)" msgstr "прозрачность окна (от 0.0 до 1.0)" #: ../screenkey:81 msgid "Ignore the specified KeySym" msgstr "Игнорировать указанный символ" #: ../screenkey:83 msgid "Compress key repeats after the specified count" msgstr "Сокращать повторы после достижения указанного количества" #~ msgid "Aspect" #~ msgstr "Сторона" #~ msgid "Bright+" #~ msgstr "Яркость+" screenkey-v1.5/Screenkey/locale/uk/000077500000000000000000000000001415444532700173545ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/uk/LC_MESSAGES/000077500000000000000000000000001415444532700211415ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/uk/LC_MESSAGES/screenkey.po000066400000000000000000000053741415444532700235020ustar00rootroot00000000000000# Ukrainian translation for screenkey # Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010 # This file is distributed under the same license as the screenkey package. # FIRST AUTHOR , 2010. # msgid "" msgstr "" "Project-Id-Version: screenkey\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2010-10-07 21:38+0200\n" "PO-Revision-Date: 2016-01-26 20:41+0300\n" "Last-Translator: Igor Bronovskyi \n" "Language-Team: Ukrainian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2016-01-26 18:28+0000\n" "X-Generator: Poedit 1.5.4\n" "Language: uk_UA\n" #: Screenkey/listenkbd.py:29 msgid "Esc " msgstr "Esc " #: Screenkey/listenkbd.py:33 msgid "Caps " msgstr "Caps " #: Screenkey/listenkbd.py:46 msgid "Home " msgstr "Home " #: Screenkey/listenkbd.py:48 msgid "PgUp " msgstr "PgUp " #: Screenkey/listenkbd.py:51 msgid "End " msgstr "End " #: Screenkey/listenkbd.py:53 msgid "PgDn " msgstr "PgDn " #: Screenkey/listenkbd.py:54 msgid "Ins " msgstr "Ins " #: Screenkey/listenkbd.py:55 msgid "Del " msgstr "Del " #: Screenkey/listenkbd.py:245 msgid "Ctrl+" msgstr "Ctrl+" #: Screenkey/listenkbd.py:247 msgid "Alt+" msgstr "Alt+" #: Screenkey/listenkbd.py:249 msgid "Super+" msgstr "Super+" #: Screenkey/__init__.py:3 msgid "Screencast your keys" msgstr "Ваші клавіші для скрінкасту" #: Screenkey/screenkey.py:42 msgid "Top" msgstr "Вгорі" #: Screenkey/screenkey.py:43 msgid "Center" msgstr "По центру" #: Screenkey/screenkey.py:44 msgid "Bottom" msgstr "Внизу" #: Screenkey/screenkey.py:47 msgid "Large" msgstr "Великий" #: Screenkey/screenkey.py:48 msgid "Medium" msgstr "Середній" #: Screenkey/screenkey.py:49 msgid "Small" msgstr "Малий" #: Screenkey/screenkey.py:52 msgid "Raw" msgstr "Без обробки" #: Screenkey/screenkey.py:53 msgid "Normal" msgstr "Нормальний" #: Screenkey/screenkey.py:114 msgid "Show keys" msgstr "Показати клавіші" #: Screenkey/screenkey.py:296 msgid "Preferences" msgstr "Налаштування" #: Screenkey/screenkey.py:300 msgid "Time" msgstr "Час" #: Screenkey/screenkey.py:305 msgid "Display for" msgstr "Показати для" #: Screenkey/screenkey.py:306 msgid "seconds" msgstr "секунд" #: Screenkey/screenkey.py:323 msgid "Aspect" msgstr "Сторона" #: Screenkey/screenkey.py:331 msgid "Position" msgstr "Розташування" #: Screenkey/screenkey.py:346 msgid "Size" msgstr "Розмір" #: Screenkey/screenkey.py:363 msgid "Keys" msgstr "Клавіші" #: Screenkey/screenkey.py:368 msgid "Mode" msgstr "Режим" screenkey-v1.5/Screenkey/locale/zh_CN/000077500000000000000000000000001415444532700177365ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/zh_CN/LC_MESSAGES/000077500000000000000000000000001415444532700215235ustar00rootroot00000000000000screenkey-v1.5/Screenkey/locale/zh_CN/LC_MESSAGES/screenkey.po000066400000000000000000000347521415444532700240660ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: ScreenKey 1.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-07-24 23:25+0800\n" "PO-Revision-Date: 2020-07-25 12:14+0800\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "Last-Translator: WhiredPlanck \n" "Language-Team: \n" "X-Generator: Poedit 2.3.1\n" #: Screenkey/__init__.py:12 msgid "Screencast your keys" msgstr "Screencast your keys" #: Screenkey/__init__.py:22 msgid "Top" msgstr "顶部" #: Screenkey/__init__.py:23 msgid "Center" msgstr "中央" #: Screenkey/__init__.py:24 msgid "Bottom" msgstr "底部" #: Screenkey/__init__.py:25 msgid "Fixed" msgstr "固定位置" #: Screenkey/__init__.py:29 msgid "Large" msgstr "大" #: Screenkey/__init__.py:30 msgid "Medium" msgstr "中" #: Screenkey/__init__.py:31 msgid "Small" msgstr "小" # i18n hint: "Composed" attempts to show only the final results of key composition. # Dead keys and any intermediate output during composition is not shown. # Currently works correctly with XIM/IBUS, but only for on-the-spot editing. # It can cause problems with complex input methods (support for wider compatibility is underway). #: Screenkey/__init__.py:35 msgid "Composed" msgstr "组合" # i18n hint: "Translated" shows the result of each keypress on the keyboard, accounting for the current keyboard locale and modifiers, but not # composition. Pressing a dead key followed by a letter will show both keys. #: Screenkey/__init__.py:36 msgid "Translated" msgstr "翻译" # i18n hint: "Keysyms" shows the keysyms ("symbolic" names) of each pressed key as received by the server. Mostly useful for debugging. #: Screenkey/__init__.py:37 msgid "Keysyms" msgstr "按键名" # i18n hint: "Raw" shows which key caps were pressed on the keyboard, without translation. For example, typing "!" (which is often located on top of the key "1") requires pressing "Shift+1", which is what this output # mode shows. "Backspace mode", "Always visible Shift" and "Modifiers only" have no effect in this mode. #: Screenkey/__init__.py:38 msgid "Raw" msgstr "原始" # i18n hint: "Normal" always inserts a backspace symbol in the output window. #: Screenkey/__init__.py:42 Screenkey/__init__.py:48 msgid "Normal" msgstr "正常" # i18n hint: "Baked" simulates the effect of backspace in the text only if the last keypress is a regular letter and no caret movement has been detected. In any other case, a backspace symbol is inserted instead. #: Screenkey/__init__.py:43 msgid "Baked" msgstr "烘烤" # i18n hint: "Full" is similar to "baked", but will eat through several other, less safe keys, such as tabs and returns. #: Screenkey/__init__.py:44 msgid "Full" msgstr "完整" #: Screenkey/__init__.py:49 msgid "Emacs" msgstr "Emacs" #: Screenkey/__init__.py:50 msgid "Mac" msgstr "Mac" #: Screenkey/__init__.py:51 msgid "Windows" msgstr "Windows" #: Screenkey/__init__.py:52 msgid "Linux" msgstr "Linux" #: Screenkey/labelmanager.py:28 msgid "Esc" msgstr "Esc" #: Screenkey/labelmanager.py:29 Screenkey/labelmanager.py:30 msgid "↹" msgstr "↹" #: Screenkey/labelmanager.py:31 Screenkey/labelmanager.py:72 msgid "⏎" msgstr "⏎" #: Screenkey/labelmanager.py:32 msgid "␣" msgstr "␣" #: Screenkey/labelmanager.py:33 msgid "⌫" msgstr "⌫" #: Screenkey/labelmanager.py:34 msgid "Caps" msgstr "Caps" #: Screenkey/labelmanager.py:35 msgid "F1" msgstr "F1" #: Screenkey/labelmanager.py:36 msgid "F2" msgstr "F2" #: Screenkey/labelmanager.py:37 msgid "F3" msgstr "F3" #: Screenkey/labelmanager.py:38 msgid "F4" msgstr "F4" #: Screenkey/labelmanager.py:39 msgid "F5" msgstr "F5" #: Screenkey/labelmanager.py:40 msgid "F6" msgstr "F6" #: Screenkey/labelmanager.py:41 msgid "F7" msgstr "F7" #: Screenkey/labelmanager.py:42 msgid "F8" msgstr "F8" #: Screenkey/labelmanager.py:43 msgid "F9" msgstr "F9" #: Screenkey/labelmanager.py:44 msgid "F10" msgstr "F10" #: Screenkey/labelmanager.py:45 msgid "F11" msgstr "F11" #: Screenkey/labelmanager.py:46 msgid "F12" msgstr "F12" #: Screenkey/labelmanager.py:47 msgid "↑" msgstr "↑" #: Screenkey/labelmanager.py:48 msgid "←" msgstr "←" #: Screenkey/labelmanager.py:49 msgid "→" msgstr "→" #: Screenkey/labelmanager.py:50 msgid "↓" msgstr "↓" #: Screenkey/labelmanager.py:51 msgid "PgUp" msgstr "PgUp" #: Screenkey/labelmanager.py:52 msgid "PgDn" msgstr "PgDn" #: Screenkey/labelmanager.py:53 msgid "Home" msgstr "Home" #: Screenkey/labelmanager.py:54 msgid "End" msgstr "End" #: Screenkey/labelmanager.py:55 msgid "Ins" msgstr "Ins" #: Screenkey/labelmanager.py:56 msgid "Del" msgstr "Del" #: Screenkey/labelmanager.py:57 msgid "(1)" msgstr "(1)" #: Screenkey/labelmanager.py:58 msgid "(2)" msgstr "(2)" #: Screenkey/labelmanager.py:59 msgid "(3)" msgstr "(3)" #: Screenkey/labelmanager.py:60 msgid "(4)" msgstr "(4)" #: Screenkey/labelmanager.py:61 msgid "(5)" msgstr "(5)" #: Screenkey/labelmanager.py:62 msgid "(6)" msgstr "(6)" #: Screenkey/labelmanager.py:63 msgid "(7)" msgstr "(7)" #: Screenkey/labelmanager.py:64 msgid "(8)" msgstr "(8)" #: Screenkey/labelmanager.py:65 msgid "(9)" msgstr "(9)" #: Screenkey/labelmanager.py:66 msgid "(0)" msgstr "(0)" #: Screenkey/labelmanager.py:67 msgid "(.)" msgstr "(.)" #: Screenkey/labelmanager.py:68 msgid "(+)" msgstr "(+)" #: Screenkey/labelmanager.py:69 msgid "(-)" msgstr "(-)" #: Screenkey/labelmanager.py:70 msgid "(*)" msgstr "(*)" #: Screenkey/labelmanager.py:71 msgid "(/)" msgstr "(/)" #: Screenkey/labelmanager.py:73 msgid "NumLck" msgstr "NumLck" #: Screenkey/labelmanager.py:74 msgid "ScrLck" msgstr "ScrLck" #: Screenkey/labelmanager.py:75 msgid "Pause" msgstr "Pause" #: Screenkey/labelmanager.py:76 msgid "Break" msgstr "Break" #: Screenkey/labelmanager.py:77 msgid "Print" msgstr "Print" #: Screenkey/labelmanager.py:78 msgid "Compose" msgstr "Compose" #: Screenkey/labelmanager.py:81 Screenkey/labelmanager.py:82 msgid "\\uf026" msgstr "\\uf026" #: Screenkey/labelmanager.py:83 msgid "Mute" msgstr "静音" #: Screenkey/labelmanager.py:84 Screenkey/labelmanager.py:85 msgid "\\uf131" msgstr "\\uf131" #: Screenkey/labelmanager.py:86 msgid "Rec" msgstr "录音/麦克风" #: Screenkey/labelmanager.py:87 Screenkey/labelmanager.py:88 msgid "\\uf028" msgstr "\\uf028" #: Screenkey/labelmanager.py:89 Screenkey/labelmanager.py:92 msgid "Vol" msgstr "音量" #: Screenkey/labelmanager.py:90 Screenkey/labelmanager.py:91 msgid "\\uf027" msgstr "\\uf027" #: Screenkey/labelmanager.py:93 Screenkey/labelmanager.py:94 msgid "\\uf048" msgstr "\\uf048" #: Screenkey/labelmanager.py:95 msgid "Prev" msgstr "上一个" #: Screenkey/labelmanager.py:96 Screenkey/labelmanager.py:97 msgid "\\uf051" msgstr "\\uf051" #: Screenkey/labelmanager.py:98 msgid "Next" msgstr "下一个" #: Screenkey/labelmanager.py:99 Screenkey/labelmanager.py:100 msgid "\\uf04b" msgstr "\\uf04b" #: Screenkey/labelmanager.py:101 msgid "▶" msgstr "▶" #: Screenkey/labelmanager.py:102 Screenkey/labelmanager.py:103 msgid "\\uf04d" msgstr "\\uf04d" #: Screenkey/labelmanager.py:104 msgid "⬛" msgstr "⬛" #: Screenkey/labelmanager.py:105 Screenkey/labelmanager.py:106 msgid "\\uf052" msgstr "\\uf052" #: Screenkey/labelmanager.py:107 msgid "Eject" msgstr "弹出" #: Screenkey/labelmanager.py:108 Screenkey/labelmanager.py:109 #: Screenkey/labelmanager.py:111 Screenkey/labelmanager.py:112 msgid "\\uf185" msgstr "\\uf185" #: Screenkey/labelmanager.py:110 Screenkey/labelmanager.py:113 msgid "Bright" msgstr "亮度" #: Screenkey/labelmanager.py:114 Screenkey/labelmanager.py:115 msgid "\\uf108" msgstr "\\uf108" #: Screenkey/labelmanager.py:116 msgid "Display" msgstr "显示" #: Screenkey/labelmanager.py:117 Screenkey/labelmanager.py:118 msgid "\\uf1eb" msgstr "\\uf1eb" #: Screenkey/labelmanager.py:119 msgid "WLAN" msgstr "WLAN" #: Screenkey/labelmanager.py:120 Screenkey/labelmanager.py:121 msgid "\\uf002" msgstr "\\uf002" #: Screenkey/labelmanager.py:122 msgid "Search" msgstr "搜索" #: Screenkey/labelmanager.py:123 Screenkey/labelmanager.py:124 msgid "\\uf294" msgstr "\\uf294" #: Screenkey/labelmanager.py:125 msgid "Bluetooth" msgstr "蓝牙" #: Screenkey/labelmanager.py:126 msgid "\\uf7d9" msgstr "\\uf7d9" #: Screenkey/labelmanager.py:127 msgid "🛠" msgstr "🛠" #: Screenkey/labelmanager.py:128 Screenkey/labelmanager.py:129 msgid "\\uf005" msgstr "\\uf005" #: Screenkey/labelmanager.py:130 msgid "🟊" msgstr "🟊" #: Screenkey/labelmanager.py:145 msgid "Shift+" msgstr "Shift+" #: Screenkey/labelmanager.py:145 msgid "⇧+" msgstr "⇧+" #: Screenkey/labelmanager.py:146 msgid "Ctrl+" msgstr "Ctrl+" #: Screenkey/labelmanager.py:146 msgid "⌘+" msgstr "⌘+" #: Screenkey/labelmanager.py:147 msgid "Alt+" msgstr "Alt+" #: Screenkey/labelmanager.py:147 msgid "⌥+" msgstr "⌥+" #: Screenkey/labelmanager.py:148 msgid "Super+" msgstr "Super+" #: Screenkey/labelmanager.py:149 Screenkey/labelmanager.py:150 msgid "\\uf17a" msgstr "\\uf17a" #: Screenkey/labelmanager.py:151 msgid "Win" msgstr "Win" #: Screenkey/labelmanager.py:152 Screenkey/labelmanager.py:153 msgid "\\uf17c" msgstr "\\uf17c" #: Screenkey/labelmanager.py:154 msgid "Super" msgstr "Super" #: Screenkey/labelmanager.py:155 msgid "Hyper+" msgstr "Hyper+" #: Screenkey/labelmanager.py:156 msgid "AltGr+" msgstr "AltGr+" #: Screenkey/labelmanager.py:433 Screenkey/labelmanager.py:474 msgid "off" msgstr "关" #: Screenkey/labelmanager.py:433 Screenkey/labelmanager.py:474 msgid "on" msgstr "开" #: Screenkey/screenkey.py:289 #, python-brace-format msgid "" "Screenkey failed to initialize. This is usually a sign of an improperly " "configured input method or desktop keyboard settings. Please see the troubleshooting documentation for further diagnosing " "instructions.\n" "\n" "Screenkey cannot recover and will now quit!" msgstr "" "Screenkey 初始化失败。这通常表示输入法或桌面键盘设置配置不正确。请参阅 故障排除文档 以获取进一步的诊断说明。\n" "\n" "Screenkey 无法恢复启动,现在将退出!" #: Screenkey/screenkey.py:478 #, python-brace-format msgid "" "\"slop\" is required for interactive selection. See {url}" msgstr "交互式选择依赖 \"slop\" 软件包。参见 {url}" #: Screenkey/screenkey.py:525 msgid "Time" msgstr "显示时间" #: Screenkey/screenkey.py:533 msgid "Display for" msgstr "持续显示" #: Screenkey/screenkey.py:534 msgid "seconds" msgstr "秒" #: Screenkey/screenkey.py:547 msgid "Persistent window" msgstr "保持窗口可见" #: Screenkey/screenkey.py:554 Screenkey/screenkey.py:571 msgid "Position" msgstr "显示位置" #: Screenkey/screenkey.py:562 msgid "Screen" msgstr "屏幕" #: Screenkey/screenkey.py:580 msgid "Reset" msgstr "重置" #: Screenkey/screenkey.py:588 msgid "Select window/region" msgstr "选择窗口/区域" #: Screenkey/screenkey.py:598 Screenkey/screenkey.py:608 msgid "Font" msgstr "字体" #: Screenkey/screenkey.py:617 msgid "Size" msgstr "大小" #: Screenkey/screenkey.py:632 msgid "Keys" msgstr "按键" #: Screenkey/screenkey.py:640 msgid "Keyboard mode" msgstr "键盘模式" #: Screenkey/screenkey.py:649 msgid "Backspace mode" msgstr "退格模式" #: Screenkey/screenkey.py:658 msgid "Modifiers mode" msgstr "修饰符模式" #: Screenkey/screenkey.py:667 msgid "Show Modifier sequences only" msgstr "仅显示修饰符序列" #: Screenkey/screenkey.py:671 msgid "Always show Shift" msgstr "总是显示 Shift 按键" #: Screenkey/screenkey.py:675 msgid "Show Whitespace characters" msgstr "显示空白字符(空格和 Tab 键)" #: Screenkey/screenkey.py:680 msgid "Compress repeats after" msgstr "压缩显示重复阈值" #: Screenkey/screenkey.py:705 msgid "Color" msgstr "颜色" #: Screenkey/screenkey.py:714 msgid "Font color" msgstr "字体颜色" #: Screenkey/screenkey.py:717 msgid "Text color" msgstr "文字颜色" #: Screenkey/screenkey.py:721 Screenkey/screenkey.py:724 msgid "Background color" msgstr "背景颜色" #: Screenkey/screenkey.py:728 msgid "Opacity" msgstr "透明度" #: Screenkey/screenkey.py:762 msgid "Show keys" msgstr "显示按键" #: Screenkey/screenkey.py:768 msgid "Preferences" msgstr "偏好设置" #: Screenkey/screenkey.py:773 msgid "About" msgstr "关于" #: Screenkey/screenkey.py:782 msgid "Quit" msgstr "退出" #: screenkey:42 msgid "enable debugging" msgstr "启用调试" #: screenkey:44 msgid "do not create system tray icon" msgstr "不创建系统托盘图标" #: screenkey:45 msgid "timeout in seconds" msgstr "超时时间 (以秒为单位)" #: screenkey:47 msgid "set vertical position" msgstr "设置垂直位置" #: screenkey:49 msgid "make window persistent" msgstr "使窗口保持可见" #: screenkey:51 msgid "set font size" msgstr "设置字体大小" #: screenkey:53 msgid "set fixed area/window geometry" msgstr "设置固定区域/窗口几何形状" #: screenkey:55 msgid "set key processing mode" msgstr "设置按键处理模式" #: screenkey:57 msgid "backspace processing mode" msgstr "退格处理模式" #: screenkey:59 msgid "modifiers visualization mode" msgstr "修饰符可视化模式" #: screenkey:61 msgid "show only keys with modifiers pressed" msgstr "仅显示和修饰键一起按下的按键" #: screenkey:63 msgid "span text over multiple lines" msgstr "将文本跨越多行" #: screenkey:65 msgid "always show Shift when modifiers are pressed" msgstr "按下修饰符键时总是显示 Shift 键" #: screenkey:67 msgid "disable visualization of whitespace" msgstr "禁用空白字符可视化" #: screenkey:69 msgid "show settings dialog on start" msgstr "在启动时显示设置对话框" #: screenkey:71 msgid "show on the specified screen number" msgstr "显示在指定编号的屏幕上" #: screenkey:73 msgid "set font family/weight" msgstr "设置字体系列/字重" #: screenkey:75 msgid "set font color" msgstr "设置字体颜色" #: screenkey:77 msgid "background color" msgstr "背景颜色" #: screenkey:79 msgid "window opacity (in range 0.0-1.0)" msgstr "窗口透明度 (范围 0.0 -1.0)" #: screenkey:81 msgid "Ignore the specified KeySym" msgstr "忽略指定的按键名" #: screenkey:83 msgid "Compress key repeats after the specified count" msgstr "在指定次数后压缩重复按键的显示" #: screenkey:85 msgid "do not display anything until explicitly requested" msgstr "在明确要求之前不显示任何内容" screenkey-v1.5/Screenkey/screenkey.py000066400000000000000000001242521415444532700200460ustar00rootroot00000000000000# "screenkey" is distributed under GNU GPLv3+, WITHOUT ANY WARRANTY. # Copyright(c) 2010-2012: Pablo Seminario # Copyright(c) 2015-2020: wave++ "Yuri D'Elia" # Copyright(c) 2019-2020: Yuto Tokunaga from . import * from .labelmanager import LabelManager from datetime import datetime import json import os import subprocess import numbers from tempfile import NamedTemporaryFile import gi gi.require_version('Gtk', '3.0') gi.require_version('Pango', '1.0') from gi.repository import GLib, Gtk, Gdk, GdkPixbuf, Pango, GObject import cairo # Gtk shortcuts START = Gtk.Align.START CENTER = Gtk.Align.CENTER END = Gtk.Align.END FILL = Gtk.Align.FILL TOP = Gtk.PositionType.TOP BOTTOM = Gtk.PositionType.BOTTOM RIGHT = Gtk.PositionType.RIGHT LEFT = Gtk.PositionType.LEFT HORIZONTAL = Gtk.Orientation.HORIZONTAL VERTICAL = Gtk.Orientation.VERTICAL IF_VALID = Gtk.SpinButtonUpdatePolicy.IF_VALID BUTTONS_MIN_BLINK = 1/30 # Minimum persistence for any action (s) BUTTONS_REL_BRIGHT = 127 # Residual brightness after button release # SVG Data for mouse buttons BUTTONS_SVG = None def load_button_pixbufs(color): global BUTTONS_SVG if BUTTONS_SVG is None: image_path = os.path.join(MODULE_DIR, 'images', 'mouse.svg') with open(image_path) as svg_file: BUTTONS_SVG = svg_file.readlines() if not isinstance(color, str): # Gdk.Color color = 'rgb({}, {}, {})'.format( round(color.red_float * 255), round(color.green_float * 255), round(color.blue_float * 255) ) button_pixbufs = [] svg = NamedTemporaryFile(mode='w', suffix='.svg') for line in BUTTONS_SVG[1:-1]: svg.seek(0) svg.truncate() svg.writelines(( BUTTONS_SVG[0], line.replace('#fff', color), BUTTONS_SVG[-1], )) svg.flush() os.fsync(svg.fileno()) button_pixbufs.append(GdkPixbuf.Pixbuf.new_from_file(svg.name)) svg.close() return button_pixbufs def gi_module_available(module, version): try: gi.require_version(module, version) return True except ValueError: return False class Screenkey(Gtk.Window): STATE_FILE = os.path.join(GLib.get_user_config_dir(), 'screenkey.json') def __init__(self, logger, options, show_settings=False): self.logger = logger self.logger.debug("{} {}".format(APP_NAME, VERSION)) self.exit_status = None self.timer_hide = None self.timer_min = None defaults = Options({'no_systray': False, 'timeout': 2.5, 'recent_thr': 0.1, 'compr_cnt': 3, 'ignore': [], 'position': 'bottom', 'persist': False, 'window': False, 'font_desc': 'Sans Bold', 'font_size': 'medium', 'font_color': 'white', 'bg_color': 'black', 'opacity': 0.8, 'key_mode': 'composed', 'bak_mode': 'baked', 'mods_mode': 'normal', 'mods_only': False, 'multiline': False, 'vis_shift': False, 'vis_space': True, 'geometry': None, 'screen': 0, 'start_disabled': False, 'mouse': False, 'button_hide_duration': 1}) self.options = self.load_state() if self.options is None: self.options = defaults else: # copy missing defaults for k, v in defaults.items(): if k not in self.options: self.options[k] = v if options is not None: # override with values from constructor for k, v in options.items(): if v is not None: self.options[k] = v if not self.options.window: Gtk.Window.__init__(self, Gtk.WindowType.POPUP) else: self.options.persist = True Gtk.Window.__init__(self, Gtk.WindowType.TOPLEVEL) self.set_keep_above(True) self.set_accept_focus(False) self.set_focus_on_map(False) self.set_app_paintable(True) self.button_pixbufs = [] self.button_states = [None] * 11 self.img = Gtk.Image() self.update_image_tag = None self.box = Gtk.HBox(homogeneous=False) self.box.show() self.add(self.box) self.label = Gtk.Label() self.label.set_ellipsize(Pango.EllipsizeMode.START) self.label.set_justify(Gtk.Justification.CENTER) self.label.show() self.font = Pango.FontDescription(self.options.font_desc) self.update_colors() self.update_mouse_enabled() self.set_size_request(0, 0) self.set_gravity(Gdk.Gravity.CENTER) self.connect("configure-event", self.on_configure) self.connect("draw", self.on_draw) scr = self.get_screen() scr.connect("size-changed", self.on_screen_size_changed) scr.connect("monitors-changed", self.on_monitors_changed) self.set_active_monitor(self.options.screen) visual = scr.get_rgba_visual() if visual is not None: self.set_visual(visual) self.box.pack_start(self.img, expand=False, fill=True, padding=0) self.box.pack_end(self.label, expand=True, fill=True, padding=0) self.labelmngr = None self.enabled = True self.on_change_mode() self.make_menu() self.make_about_dialog() self.make_preferences_dialog() if not self.options.no_systray: if gi_module_available('AppIndicator3', '0.1'): self.make_appindicator() else: self.make_systray() self.connect("delete-event", self.quit) if show_settings: self.on_preferences_dialog() if self.options.persist: self.show() def quit(self, widget=None, data=None, exit_status=os.EX_OK): self.labelmngr.stop() self.exit_status = exit_status Gtk.main_quit() def load_state(self): """Load stored options""" options = None try: with open(self.STATE_FILE) as f: options = Options(json.load(f)) self.logger.debug("Options loaded.") except OSError: self.logger.debug("file %s does not exists." % self.STATE_FILE) except ValueError: self.logger.debug("file %s is invalid." % self.STATE_FILE) # compatibility with previous versions (0.5) if options and options.key_mode == 'normal': options.key_mode = 'composed' return options def store_state(self, options): """Store options""" try: with open(self.STATE_FILE, 'w') as f: json.dump(options._store, f, indent=4) self.logger.debug("Options saved.") except OSError: self.logger.debug("Cannot open %s." % self.STATE_FILE) def set_active_monitor(self, monitor): scr = self.get_screen() if monitor >= scr.get_n_monitors(): self.monitor = 0 else: self.monitor = monitor self.update_geometry() def on_monitors_changed(self, monitor): self.set_active_monitor(self.monitor) def update_mouse_enabled(self): if self.options.mouse: if not self.button_pixbufs: self.button_pixbufs = load_button_pixbufs( Gdk.color_parse(self.options.font_color) ) self.img.show() self.update_image_tag = GLib.idle_add(self.update_image) else: self.img.hide() if self.update_image_tag is not None: GLib.source_remove(self.update_image_tag) self.update_image_tag = None def do_get_preferred_height(self): return self.height def update_font(self): text = self.label.get_text() lines = text.count('\n') + 1 self.font.set_absolute_size((50 * self.height // lines // 100) * 1000) self.label.set_padding(self.width // 100, 0) self.label.get_pango_context().set_font_description(self.font) def update_image(self): if not self.button_pixbufs: self.update_image_tag = None return False pixbuf = self.button_pixbufs[0] copied = False for index, button_state in enumerate(self.button_states): if button_state is None: continue delta_time = (datetime.now() - button_state.stamp).total_seconds() if button_state.pressed or delta_time < BUTTONS_MIN_BLINK: alpha = 255 elif self.options.button_hide_duration > 0: hide_time = delta_time / self.options.button_hide_duration alpha = int(BUTTONS_REL_BRIGHT * (1 - min(1, hide_time))) else: alpha = 0 if not copied: pixbuf = pixbuf.copy() copied = True self.button_pixbufs[button_state.btn].composite( pixbuf, 0, 0, pixbuf.get_width(), pixbuf.get_height(), 0, 0, 1, 1, GdkPixbuf.InterpType.NEAREST, alpha) if not button_state.pressed and \ delta_time >= self.options.button_hide_duration: self.button_states[index] = None scale = self.height / pixbuf.get_height() if scale != 1: width = int(pixbuf.get_width() * scale) pixbuf = pixbuf.scale_simple(width, self.height, GdkPixbuf.InterpType.BILINEAR) self.img.set_from_pixbuf(pixbuf) if not copied: self.update_image_tag = None return False return True def update_colors(self): font_color = Gdk.color_parse(self.options.font_color) self.label.modify_fg(Gtk.StateFlags.NORMAL, font_color) self.bg_color = Gdk.color_parse(self.options.bg_color) if self.options.mouse and self.button_pixbufs: self.button_pixbufs = load_button_pixbufs(font_color) self.queue_draw() def on_draw(self, widget, cr): cr.set_source_rgba(self.bg_color.red_float, self.bg_color.green_float, self.bg_color.blue_float, self.options.opacity) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() cr.set_operator(cairo.OPERATOR_OVER) return False def on_configure(self, event, data): # set event mask for click-through self.input_shape_combine_region(cairo.Region(cairo.RectangleInt(0, 0, 0, 0))) def on_screen_size_changed(self, screen): self.width, self.height = self.get_size() self.update_font() self.update_image() def update_geometry(self, configure=False): geometry = self.get_screen().get_monitor_geometry(self.monitor) if self.options.geometry is not None: # NOTE: this assume a single global scaling factor for all # monitors which seems to be true for GTK3: # https://wiki.gnome.org/HowDoI/HiDpi scale = self.get_screen().get_monitor_scale_factor(self.monitor) # scale the coordinate according to the selected monitor # or convert from device to gdk pixel units def coord_to_gdk(coord, extent): if not isinstance(coord, numbers.Integral): return int(coord * extent) else: return int(coord / scale) x, y, w, h = self.options.geometry x = coord_to_gdk(x, geometry.width) y = coord_to_gdk(y, geometry.height) w = coord_to_gdk(w, geometry.width) h = coord_to_gdk(h, geometry.height) if x < 0: x = geometry.width + x - w if y < 0: y = geometry.height + y - h area_geometry = [x, y, w, h] else: area_geometry = [geometry.x, geometry.y, geometry.width, geometry.height] if self.options.position == 'fixed': self.move_resize(*area_geometry) return if self.options.font_size == 'large': window_height = 24 * area_geometry[3] // 100 elif self.options.font_size == 'medium': window_height = 12 * area_geometry[3] // 100 else: window_height = 8 * area_geometry[3] // 100 if self.options.position == 'top': window_y = area_geometry[1] + area_geometry[3] // 10 elif self.options.position == 'center': window_y = area_geometry[1] + area_geometry[3] // 2 - window_height // 2 else: window_y = area_geometry[1] + area_geometry[3] * 9 // 10 - window_height self.move_resize(area_geometry[0], window_y, area_geometry[2], window_height) def move_resize(self, x, y, w, h): self.width = w self.height = h self.move(x, y) self.resize(w, h) def on_statusicon_popup(self, widget, button, timestamp, data=None): if button == 3 and data: data.show() data.popup_at_pointer(None) def on_labelmngr_error(self): msg = Gtk.MessageDialog(parent=self, type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK, message_format="Error initializing Screenkey") text = _('Screenkey failed to initialize. This is usually a sign of an improperly ' 'configured input method or desktop keyboard settings. Please see the troubleshooting documentation for further diagnosing ' 'instructions.\n\nScreenkey cannot recover and will now quit!') msg.format_secondary_markup(text.format(url=ERROR_URL)) msg.run() msg.destroy() self.quit(exit_status=os.EX_SOFTWARE) def timed_show(self): if not self.get_property('visible'): self.show() if self.timer_hide is not None: GObject.source_remove(self.timer_hide) self.timer_hide = None if self.options.timeout > 0: # hide automatically if mouse mode is disabled. keep the # window around otherwise as long as any of the visible keys # (mouse or modifiers) is still held if not self.options.mouse or \ not any(b and b.pressed for b in self.button_states): self.timer_hide = GObject.timeout_add(self.options.timeout * 1000, self.on_timeout_main) def on_label_change(self, markup, synthetic): if markup is None: self.on_labelmngr_error() return _, attr, text, _ = Pango.parse_markup(markup, -1, '\0') self.label.set_text(text) self.label.set_attributes(attr) self.update_font() self.timed_show() if self.timer_min is not None: GObject.source_remove(self.timer_min) self.timer_min = None if not synthetic: self.timer_min = GObject.timeout_add(self.options.recent_thr * 2000, self.on_timeout_min) def on_image_change(self, button_state): if button_state: btn = button_state.btn # Don't do animation after stealth enable if self.button_states[btn] is not None or button_state.pressed: self.button_states[btn] = button_state if self.options.mouse: if not self.update_image_tag: self.update_image_tag = GLib.idle_add(self.update_image) self.timed_show() else: # Reset all self.button_states = [None for _ in self.button_states] if self.options.mouse: if not self.update_image_tag: self.update_image_tag = GLib.idle_add(self.update_image) self.timed_show() def on_timeout_main(self): if not self.options.persist: self.hide() self.timer_hide = None self.label.set_text('') self.labelmngr.clear() return False def on_timeout_min(self): self.timer_min = None self.labelmngr.queue_update() return False def restart_labelmanager(self): self.logger.debug("Restarting LabelManager.") if self.labelmngr: self.labelmngr.stop() self.labelmngr = LabelManager(self.on_label_change, self.on_image_change, logger=self.logger, key_mode=self.options.key_mode, bak_mode=self.options.bak_mode, mods_mode=self.options.mods_mode, mods_only=self.options.mods_only, multiline=self.options.multiline, vis_shift=self.options.vis_shift, vis_space=self.options.vis_space, recent_thr=self.options.recent_thr, compr_cnt=self.options.compr_cnt, ignore=self.options.ignore, pango_ctx=self.label.get_pango_context(), enabled=not self.options.start_disabled) self.labelmngr.start() def on_change_mode(self): if not self.enabled: return self.restart_labelmanager() def on_show_keys(self, widget, data=None): self.enabled = widget.get_active() if self.enabled: self.logger.debug("Screenkey enabled.") self.restart_labelmanager() else: self.logger.debug("Screenkey disabled.") self.labelmngr.stop() def on_preferences_dialog(self, widget=None, data=None): self.prefs.show() def on_preferences_changed(self, widget=None, data=None): self.store_state(self.options) self.prefs.hide() return True def make_preferences_dialog(self): # TODO: switch to something declarative or at least clean-up the following mess self.prefs = prefs = Gtk.Dialog(APP_NAME, None, Gtk.DialogFlags.DESTROY_WITH_PARENT, (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), use_header_bar=True, destroy_with_parent=True, resizable=False) prefs.connect("response", self.on_preferences_changed) prefs.connect("delete-event", self.on_preferences_changed) def on_sb_time_changed(widget, data=None): self.options.timeout = widget.get_value() self.logger.debug("Timeout value changed: %f." % self.options.timeout) def on_cbox_sizes_changed(widget, data=None): self.options.font_size = widget.props.active_id self.update_geometry() self.logger.debug("Window size changed: %s." % self.options.font_size) def on_cbox_modes_changed(widget, data=None): self.options.key_mode = widget.props.active_id self.on_change_mode() self.logger.debug("Key mode changed: %s." % self.options.key_mode) def on_cbox_bak_changed(widget, data=None): self.options.bak_mode = widget.props.active_id self.on_change_mode() self.logger.debug("Bak mode changed: %s." % self.options.bak_mode) def on_cbox_mods_changed(widget, data=None): self.options.mods_mode = widget.props.active_id self.on_change_mode() self.logger.debug("Mods mode changed: %s." % self.options.mods_mode) def on_cbox_modsonly_changed(widget, data=None): self.options.mods_only = widget.get_active() self.on_change_mode() self.logger.debug("Modifiers only changed: %s." % self.options.mods_only) def on_cbox_visshift_changed(widget, data=None): self.options.vis_shift = widget.get_active() self.on_change_mode() self.logger.debug("Visible Shift changed: %s." % self.options.vis_shift) def on_cbox_visspace_changed(widget, data=None): self.options.vis_space = widget.get_active() self.on_change_mode() self.logger.debug("Show Whitespace changed: %s." % self.options.vis_space) def on_cbox_position_changed(widget, data=None): new_position = widget.props.active_id if self.options.position != 'fixed' and new_position == 'fixed': new_geom = on_btn_sel_geom(widget) if not new_geom: self.cbox_positions.props.active_id = self.options.position return self.options.position = new_position self.update_geometry() self.logger.debug("Window position changed: %s." % self.options.position) def on_cbox_screen_changed(widget, data=None): self.options.screen = widget.get_active() self.set_active_monitor(self.options.screen) self.logger.debug("Screen changed: %d." % self.options.screen) def on_cbox_persist_changed(widget, data=None): self.options.persist = widget.get_active() if not self.get_property('visible'): self.show() else: self.on_label_change(self.label.get_text(), True) self.logger.debug("Persistent changed: %s." % self.options.persist) def on_sb_compr_changed(widget, data=None): self.options.compr_cnt = widget.get_value_as_int() self.on_change_mode() self.logger.debug("Compress repeats value changed: %d." % self.options.compr_cnt) def on_cbox_compr_changed(widget, data=None): compr_enabled = widget.get_active() self.sb_compr.set_sensitive(compr_enabled) self.options.compr_cnt = self.sb_compr.get_value_as_int() if compr_enabled else 0 self.on_change_mode() self.logger.debug("Compress repeats value changed: %d." % self.options.compr_cnt) def on_btn_sel_geom(widget, data=None): try: ret = subprocess.check_output(['slop', '-f', '%x %y %w %h %i']) except subprocess.CalledProcessError: return False except OSError: msg = Gtk.MessageDialog(parent=self, type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK, message_format="Error running \"slop\"") msg.format_secondary_markup(_("\"slop\" is required for interactive selection. " "See {url}").format(url=SLOP_URL)) msg.run() msg.destroy() return False ret = ret.decode("utf8") data = list(map(int, ret.split(' '))) self.options.geometry = data[0:4] self.options.window = data[4] if not self.options.window or \ self.options.window == self.get_screen().get_root_window().get_xid(): # region selected, switch to fixed self.options.window = None self.options.position = 'fixed' self.cbox_positions.props.active_id = self.options.position self.update_geometry() self.btn_reset_geom.set_sensitive(True) return True def on_btn_reset_geom(widget, data=None): self.options.geometry = None if self.options.position == 'fixed': self.options.position = 'bottom' self.cbox_positions.props.active_id = self.options.position self.update_geometry() widget.set_sensitive(False) def on_adj_opacity_changed(widget, data=None): self.options.opacity = widget.get_value() self.update_colors() def on_font_color_changed(widget, data=None): self.options.font_color = widget.get_color().to_string() self.update_colors() def on_bg_color_changed(widget, data=None): self.options.bg_color = widget.get_color().to_string() self.update_colors() def on_btn_font(widget, data=None): widget.props.label = widget.props.font self.options.font_desc = widget.props.font self.font = widget.props.font_desc self.update_font() def on_cbox_mouse_changed(widget, data=None): self.options.mouse = widget.get_active() self.logger.debug("Mouse changed: %s." % self.options.mouse) self.update_mouse_enabled() def on_sb_mouse_duration_changed(widget, data=None): self.options.button_hide_duration = widget.get_value() self.logger.debug("Button hide duration value changed: %f." % self.options.button_hide_duration) frm_time = Gtk.Frame(label_widget=Gtk.Label("%s" % _("Time"), use_markup=True), border_width=4, shadow_type=Gtk.ShadowType.NONE, margin=6, hexpand=True) vbox_time = Gtk.Grid(orientation=VERTICAL, row_spacing=6, margin=6) hbox_time = Gtk.Grid(column_spacing=6) lbl_time1 = Gtk.Label(_("Display for")) lbl_time2 = Gtk.Label(_("seconds")) sb_time = Gtk.SpinButton(digits=1, numeric=True, update_policy=IF_VALID) sb_time.set_increments(0.5, 1.0) sb_time.set_range(0, 300) sb_time.set_value(self.options.timeout) sb_time.connect("value-changed", on_sb_time_changed) hbox_time.add(lbl_time1) hbox_time.add(sb_time) hbox_time.add(lbl_time2) vbox_time.add(hbox_time) chk_persist = Gtk.CheckButton(_("Persistent window"), active=self.options.persist) chk_persist.connect("toggled", on_cbox_persist_changed) vbox_time.add(chk_persist) frm_time.add(vbox_time) frm_position = Gtk.Frame(label_widget=Gtk.Label("%s" % _("Position"), use_markup=True), border_width=4, shadow_type=Gtk.ShadowType.NONE, margin=6, hexpand=True) grid_position = Gtk.Grid(row_spacing=6, column_spacing=6, margin=6) lbl_screen = Gtk.Label(_("Screen"), halign=START) cbox_screen = Gtk.ComboBoxText() scr = self.get_screen() for i in range(scr.get_n_monitors()): cbox_screen.insert_text(i, '%d: %s' % (i, scr.get_monitor_plug_name(i))) cbox_screen.set_active(self.monitor) cbox_screen.connect("changed", on_cbox_screen_changed) lbl_positions = Gtk.Label(_("Position"), halign=START) self.cbox_positions = Gtk.ComboBoxText(name='position') for id_, text in POSITIONS.items(): self.cbox_positions.append(id_, text) if id_ == self.options.position: self.cbox_positions.props.active_id = id_ self.cbox_positions.connect("changed", on_cbox_position_changed) self.btn_reset_geom = Gtk.Button(_("Reset")) self.btn_reset_geom.connect("clicked", on_btn_reset_geom) self.btn_reset_geom.set_sensitive(self.options.geometry is not None) hbox_position = Gtk.Grid(column_spacing=6, halign=END) hbox_position.add(self.cbox_positions) hbox_position.add(self.btn_reset_geom) btn_sel_geom = Gtk.Button(_("Select window/region"), halign=FILL, hexpand=True) btn_sel_geom.connect("clicked", on_btn_sel_geom) grid_position.add(lbl_screen) grid_position.attach_next_to(cbox_screen, lbl_screen, RIGHT, 1, 1) grid_position.attach_next_to(lbl_positions, lbl_screen, BOTTOM, 1, 1) grid_position.attach_next_to(hbox_position, lbl_positions, RIGHT, 1, 1) grid_position.attach_next_to(btn_sel_geom, lbl_positions, BOTTOM, 2, 1) frm_aspect = Gtk.Frame(label_widget=Gtk.Label("%s" % _("Font"), use_markup=True), border_width=4, shadow_type=Gtk.ShadowType.NONE, margin=6, hexpand=True) grid_aspect = Gtk.Grid(row_spacing=6, column_spacing=6, margin=6) frm_position.add(grid_position) lbl_font = Gtk.Label(_("Font"), hexpand=True, halign=START) btn_font = Gtk.FontButton(self.options.font_desc, font=self.options.font_desc, use_font=True, show_size=False) if Gtk.check_version(3, 23, 0) is None: btn_font.set_level(Gtk.FontChooserLevel.STYLE) btn_font.connect("font-set", on_btn_font) lbl_sizes = Gtk.Label(_("Size"), halign=START) cbox_sizes = Gtk.ComboBoxText(name='size') for id_, text in FONT_SIZES.items(): cbox_sizes.append(id_, text) if id_ == self.options.font_size: cbox_sizes.props.active_id = id_ cbox_sizes.connect("changed", on_cbox_sizes_changed) grid_aspect.add(lbl_font) grid_aspect.attach_next_to(btn_font, lbl_font, RIGHT, 1, 1) grid_aspect.attach_next_to(lbl_sizes, lbl_font, BOTTOM, 1, 1) grid_aspect.attach_next_to(cbox_sizes, lbl_sizes, RIGHT, 1, 1) frm_aspect.add(grid_aspect) frm_kbd = Gtk.Frame(label_widget=Gtk.Label("%s" % _("Keys"), use_markup=True), border_width=4, shadow_type=Gtk.ShadowType.NONE, margin=6) grid_kbd = Gtk.Grid(row_spacing=6, column_spacing=6, margin=6) lbl_modes = Gtk.Label(_("Keyboard mode"), halign=START) cbox_modes = Gtk.ComboBoxText(name='mode') for id_, text in KEY_MODES.items(): cbox_modes.append(id_, text) if id_ == self.options.key_mode: cbox_modes.props.active_id = id_ cbox_modes.connect("changed", on_cbox_modes_changed) lbl_bak = Gtk.Label(_("Backspace mode"), halign=START) cbox_bak = Gtk.ComboBoxText() for id_, text in BAK_MODES.items(): cbox_bak.append(id_, text) if id_ == self.options.bak_mode: cbox_bak.props.active_id = id_ cbox_bak.connect("changed", on_cbox_bak_changed) lbl_mods = Gtk.Label(_("Modifiers mode"), halign=START) cbox_mods = Gtk.ComboBoxText() for id_, text in MODS_MODES.items(): cbox_mods.append(id_, text) if id_ == self.options.mods_mode: cbox_mods.props.active_id = id_ cbox_mods.connect("changed", on_cbox_mods_changed) chk_modsonly = Gtk.CheckButton(_("Show Modifier sequences only"), active=self.options.mods_only) chk_modsonly.connect("toggled", on_cbox_modsonly_changed) chk_visshift = Gtk.CheckButton(_("Always show Shift"), active=self.options.vis_shift) chk_visshift.connect("toggled", on_cbox_visshift_changed) chk_visspace = Gtk.CheckButton(_("Show Whitespace characters"), active=self.options.vis_space) chk_visspace.connect("toggled", on_cbox_visspace_changed) hbox_compr = Gtk.Grid(column_spacing=6) chk_compr = Gtk.CheckButton(_("Compress repeats after"), active=self.options.compr_cnt > 0) chk_compr.connect("toggled", on_cbox_compr_changed) self.sb_compr = Gtk.SpinButton(digits=0, numeric=True, update_policy=IF_VALID) self.sb_compr.set_increments(1, 1) self.sb_compr.set_range(1, 100) self.sb_compr.set_value(self.options.compr_cnt or 3) self.sb_compr.connect("value-changed", on_sb_compr_changed) hbox_compr.add(chk_compr) hbox_compr.add(self.sb_compr) grid_kbd.add(lbl_modes) grid_kbd.attach_next_to(cbox_modes, lbl_modes, RIGHT, 1, 1) grid_kbd.attach_next_to(lbl_bak, lbl_modes, BOTTOM, 1, 1) grid_kbd.attach_next_to(cbox_bak, lbl_bak, RIGHT, 1, 1) grid_kbd.attach_next_to(lbl_mods, lbl_bak, BOTTOM, 1, 1) grid_kbd.attach_next_to(cbox_mods, lbl_mods, RIGHT, 1, 1) grid_kbd.attach_next_to(chk_modsonly, lbl_mods, BOTTOM, 2, 1) grid_kbd.attach_next_to(chk_visshift, chk_modsonly, BOTTOM, 2, 1) grid_kbd.attach_next_to(chk_visspace, chk_visshift, BOTTOM, 2, 1) grid_kbd.attach_next_to(hbox_compr, chk_visspace, BOTTOM, 2, 1) frm_kbd.add(grid_kbd) frm_color = Gtk.Frame(label_widget=Gtk.Label("%s" % _("Color"), use_markup=True), border_width=4, shadow_type=Gtk.ShadowType.NONE, margin=6) grid_color = Gtk.Grid(orientation=VERTICAL, row_spacing=6, column_spacing=6, margin=6) lbl_font_color = Gtk.Label(_("Font color"), halign=START) btn_font_color = Gtk.ColorButton(color=Gdk.color_parse(self.options.font_color), title=_("Text color"), halign=END) btn_font_color.connect("color-set", on_font_color_changed) lbl_bg_color = Gtk.Label(_("Background color"), halign=START) btn_bg_color = Gtk.ColorButton(color=Gdk.color_parse(self.options.bg_color), title=_("Background color"), halign=END) btn_bg_color.connect("color-set", on_bg_color_changed) lbl_opacity = Gtk.Label(_("Opacity"), halign=START) adj_opacity = Gtk.Adjustment(self.options.opacity, 0, 1.0, 0.1, 0, 0) adj_opacity.connect("value-changed", on_adj_opacity_changed) adj_scale = Gtk.Scale(adjustment=adj_opacity, hexpand=True, halign=FILL) grid_color.add(lbl_font_color) grid_color.attach_next_to(btn_font_color, lbl_font_color, RIGHT, 1, 1) grid_color.attach_next_to(lbl_bg_color, lbl_font_color, BOTTOM, 1, 1) grid_color.attach_next_to(btn_bg_color, lbl_bg_color, RIGHT, 1, 1) grid_color.attach_next_to(lbl_opacity, lbl_bg_color, BOTTOM, 1, 1) grid_color.attach_next_to(adj_scale, lbl_opacity, RIGHT, 1, 1) frm_color.add(grid_color) frm_mouse = Gtk.Frame(label_widget=Gtk.Label("%s" % _("Mouse"), use_markup=True), border_width=4, shadow_type=Gtk.ShadowType.NONE, margin=6, hexpand=True) vbox_mouse = Gtk.VBox(spacing=6) chk_mouse = Gtk.CheckButton(_("Show Mouse")) chk_mouse.connect("toggled", on_cbox_mouse_changed) chk_mouse.set_active(self.options.mouse) vbox_mouse.pack_start(chk_mouse, expand=False, fill=True, padding=0) hbox_mouse = Gtk.HBox() lbl_mouse1 = Gtk.Label(_("Hide duration")) lbl_mouse2 = Gtk.Label(_("seconds")) sb_mouse = Gtk.SpinButton(digits=1) sb_mouse.set_increments(0.5, 1.0) sb_mouse.set_range(0.0, 2.0) sb_mouse.set_numeric(True) sb_mouse.set_update_policy(Gtk.SpinButtonUpdatePolicy.IF_VALID) sb_mouse.set_value(self.options.button_hide_duration) sb_mouse.connect("value-changed", on_sb_mouse_duration_changed) hbox_mouse.pack_start(lbl_mouse1, expand=False, fill=False, padding=6) hbox_mouse.pack_start(sb_mouse, expand=False, fill=False, padding=4) hbox_mouse.pack_start(lbl_mouse2, expand=False, fill=False, padding=4) vbox_mouse.pack_start(hbox_mouse, expand=False, fill=False, padding=6) frm_mouse.add(vbox_mouse) frm_mouse.show_all() hbox_main = Gtk.Grid(column_homogeneous=True) vbox_main = Gtk.Grid(orientation=VERTICAL) vbox_main.add(frm_time) vbox_main.add(frm_position) vbox_main.add(frm_aspect) hbox_main.add(vbox_main) vbox_main = Gtk.Grid(orientation=VERTICAL) vbox_main.add(frm_kbd) vbox_main.add(frm_color) vbox_main.add(frm_mouse) hbox_main.add(vbox_main) box = prefs.get_content_area() box.add(hbox_main) box.show_all() def make_menu(self): self.menu = menu = Gtk.Menu() show_item = Gtk.CheckMenuItem(_("Show keys")) show_item.set_active(True) show_item.connect("toggled", self.on_show_keys) show_item.show() menu.append(show_item) preferences_item = Gtk.MenuItem(_("Preferences")) preferences_item.connect("activate", self.on_preferences_dialog) preferences_item.show() menu.append(preferences_item) about_item = Gtk.MenuItem(_("About")) about_item.connect("activate", self.on_about_dialog) about_item.show() menu.append(about_item) separator_item = Gtk.SeparatorMenuItem() separator_item.show() menu.append(separator_item) image = Gtk.MenuItem(_("Quit")) image.connect("activate", self.quit) image.show() menu.append(image) menu.show() def make_appindicator(self): from gi.repository import AppIndicator3 as AppIndicator self.systray = AppIndicator.Indicator.new( APP_NAME, 'indicator-messages', AppIndicator.IndicatorCategory.APPLICATION_STATUS) self.systray.set_status(AppIndicator.IndicatorStatus.ACTIVE) self.systray.set_attention_icon("indicator-messages-new") self.systray.set_icon("preferences-desktop-keyboard-shortcuts") self.systray.set_menu(self.menu) self.logger.debug("Using AppIndicator.") def make_systray(self): self.systray = Gtk.StatusIcon() self.systray.set_from_icon_name("preferences-desktop-keyboard-shortcuts") self.systray.connect("popup-menu", self.on_statusicon_popup, self.menu) self.logger.debug("Using StatusIcon.") def make_about_dialog(self): self.about = about = Gtk.AboutDialog() about.set_program_name(APP_NAME) about.set_version(VERSION) about.set_copyright(""" Copyright(c) 2010-2012: Pablo Seminario Copyright(c) 2015-2020: wave++ "Yuri D'Elia" Copyright(c) 2019-2020: Yuto Tokunaga """) about.set_comments(APP_DESC) about.set_documenters( ["José María Quiroga "] ) about.set_website(APP_URL) about.set_icon_name('preferences-desktop-keyboard-shortcuts') about.set_logo_icon_name('preferences-desktop-keyboard-shortcuts') about.connect("response", lambda *_: about.hide_on_delete()) about.connect("delete-event", lambda *_: about.hide_on_delete()) def on_about_dialog(self, widget, data=None): self.about.show() def start_lockscreen_detection(self): from re import match from threading import Thread from dbus import SessionBus from dbus.mainloop.glib import DBusGMainLoop def filter_bus_message(bus, message): message_member = message.get_member() if not self.enabled or message_member != "ActiveChanged": return args_list = message.get_args_list() if args_list[0]: self.labelmngr.stop() self.logger.debug("Lock Screen; Screenkey disabled.") else: self.restart_labelmanager() self.logger.debug("Unlock Screen; Screenkey enabled.") def lockscreen_detection_loop(): DBusGMainLoop(set_as_default=True) session_bus = SessionBus() signal_interface = None for dbus_string in session_bus.list_names(): bus_name = str(dbus_string) if match(r"org\.(\w+)\.ScreenSaver", bus_name): signal_interface = bus_name self.logger.debug(f"DBUS signal interface found: \"{signal_interface}\" ; password should not show when unlocking the screen.") break if not signal_interface: self.logger.debug("ScreenSaver DBUS signal interface not found; beware: password may show when unlocking the screen!") del(session_bus) DBusGMainLoop(set_as_default=False) return session_bus.add_match_string(f"type='signal',interface='{signal_interface}'") session_bus.add_message_filter(filter_bus_message) mainloop = GLib.MainLoop() mainloop.run() thread = Thread(target=lockscreen_detection_loop) thread.daemon = True thread.start() def run(self): self.start_lockscreen_detection() Gtk.main() return self.exit_status screenkey-v1.5/Screenkey/xlib.py000066400000000000000000000317631415444532700170200ustar00rootroot00000000000000# Distributed under the GNU GPLv3+ license, WITHOUT ANY WARRANTY. # Copyright(c) 2015: wave++ "Yuri D'Elia" from ctypes import * ## base X11 libX11 = CDLL('libX11.so.6') # types Atom = c_ulong Bool = c_int XID = c_ulong Colormap = XID Cursor = XID KeyCode = c_ubyte KeySym = XID Pixmap = XID Status = c_int String = c_char_p Time = c_ulong Window = XID class Display(Structure): pass class Visual(Structure): pass class XKeyEvent(Structure): _fields_ = [('type', c_int), ('serial', c_ulong), ('send_event', Bool), ('display', POINTER(Display)), ('window', Window), ('root', Window), ('subwindow', Window), ('time', Time), ('x', c_int), ('y', c_int), ('x_root', c_int), ('y_root', c_int), ('state', c_uint), ('keycode', c_uint), ('same_screen', Bool)] XKeyPressedEvent = XKeyEvent XKeyReleasedEvent = XKeyEvent class XButtonEvent(Structure): _fields_ = [('type', c_int), ('serial', c_ulong), ('send_event', Bool), ('display', POINTER(Display)), ('window', Window), ('root', Window), ('subwindow', Window), ('time', Time), ('x', c_int), ('y', c_int), ('x_root', c_int), ('y_root', c_int), ('state', c_uint), ('button', c_uint), ('same_screen', Bool)] class XMotionEvent(Structure): _fields_ = [('type', c_int), ('serial', c_ulong), ('send_event', Bool), ('display', POINTER(Display)), ('window', Window), ('root', Window), ('subwindow', Window), ('time', Time), ('x', c_int), ('y', c_int), ('x_root', c_int), ('y_root', c_int), ('state', c_uint), ('is_hint', c_ubyte), ('same_screen', Bool)] class XClientMessageEvent(Structure): _fields_ = [('type', c_int), ('serial', c_ulong), ('send_event', Bool), ('display', POINTER(Display)), ('window', Window), ('message_type', Atom), ('format', c_int), ('data', c_long * 5)] class XEvent(Union): _fields_ = [('type', c_int), ('xkey', XKeyEvent), ('xbutton', XButtonEvent), ('xmotion', XMotionEvent), ('xclient', XClientMessageEvent), ('pad', c_long * 24)] class XSetWindowAttributes(Structure): _fields_ = [('background_pixmap', Pixmap), ('background_pixel', c_ulong), ('border_pixmap', Pixmap), ('border_pixel', c_ulong), ('bit_gravity', c_int), ('win_gravity', c_int), ('backing_store', c_int), ('backing_planes', c_ulong), ('backing_pixel', c_ulong), ('save_under', Bool), ('event_mask', c_long), ('do_not_propagate_mask', c_long), ('override_redirect', Bool), ('colormap', Colormap), ('cursor', Cursor)] # constants KeyPress = 2 KeyRelease = 3 ButtonPress = 4 ButtonRelease = 5 MotionNotify = 6 FocusIn = 9 FocusOut = 10 ClientMessage = 33 CopyFromParent = 0 InputOnly = 2 CWOverrideRedirect = (1<<9) ShiftMask = (1<<0) LockMask = (1<<1) ControlMask = (1<<2) Mod1Mask = (1<<3) Mod2Mask = (1<<4) Mod3Mask = (1<<5) Mod4Mask = (1<<6) Mod5Mask = (1<<7) # functions XOpenDisplay = libX11.XOpenDisplay XOpenDisplay.argtypes = [String] XOpenDisplay.restype = POINTER(Display) XCloseDisplay = libX11.XCloseDisplay XCloseDisplay.argtypes = [POINTER(Display)] XCloseDisplay.restype = c_int XConnectionNumber = libX11.XConnectionNumber XConnectionNumber.argtypes = [POINTER(Display)] XConnectionNumber.restype = c_int XInternAtom = libX11.XInternAtom XInternAtom.argtypes = [POINTER(Display), String, Bool] XInternAtom.restype = c_int XDefaultRootWindow = libX11.XDefaultRootWindow XDefaultRootWindow.argtypes = [POINTER(Display)] XDefaultRootWindow.restype = Window XCreateWindow = libX11.XCreateWindow XCreateWindow.argtypes = [POINTER(Display), Window, c_int, c_int, c_uint, c_uint, c_uint, c_int, c_uint, POINTER(Visual), c_ulong, POINTER(XSetWindowAttributes)] XCreateWindow.restype = Window XDestroyWindow = libX11.XDestroyWindow XDestroyWindow.argtypes = [POINTER(Display), Window] XDestroyWindow.restype = c_int XFree = libX11.XFree XFree.argtypes = [POINTER(None)] XFree.restype = c_int XNextEvent = libX11.XNextEvent XNextEvent.argtypes = [POINTER(Display), POINTER(XEvent)] XNextEvent.restype = c_int XPeekEvent = libX11.XPeekEvent XPeekEvent.argtypes = [POINTER(Display), POINTER(XEvent)] XPeekEvent.restype = c_int XSendEvent = libX11.XSendEvent XSendEvent.argtypes = [POINTER(Display), Window, c_int, c_long, POINTER(XEvent)] XSendEvent.restype = c_int XFlush = libX11.XFlush XFlush.argtypes = [POINTER(Display)] XFlush.restype = c_int XPending = libX11.XPending XPending.argtypes = [POINTER(Display)] XPending.restype = c_int XSynchronize = libX11.XSynchronize XSynchronize.argtypes = [POINTER(Display), c_int] XSynchronize.restype = POINTER(CFUNCTYPE(c_int, POINTER(Display))) ## xim # types class _XIC(Structure): pass XIC = POINTER(_XIC) class _XIM(Structure): pass XIM = POINTER(_XIM) class _XrmDatabase(Structure): pass XrmDatabase = POINTER(_XrmDatabase) # constants XNInputStyle = b'inputStyle' XNClientWindow = b'clientWindow' XIMPreeditNothing = 0x0008 XIMPreeditNone = 0x0010 XIMStatusNothing = 0x0400 XIMStatusNone = 0x0800 XBufferOverflow = -1 NoSymbol = 0 XLookupNone = 1 XLookupChars = 2 XLookupKeySym = 3 XLookupBoth = 4 # functions XFilterEvent = libX11.XFilterEvent XFilterEvent.argtypes = [POINTER(XEvent), Window] XFilterEvent.restype = c_int XOpenIM = libX11.XOpenIM XOpenIM.argtypes = [POINTER(Display), XrmDatabase, String, String] XOpenIM.restype = XIM XCloseIM = libX11.XCloseIM XCloseIM.argtypes = [XIM] XCloseIM.restype = c_int XCreateIC = libX11.XCreateIC XCreateIC.restype = XIC XDestroyIC = libX11.XDestroyIC XDestroyIC.argtypes = [XIC] XDestroyIC.restype = None XSetICFocus = libX11.XSetICFocus XSetICFocus.argtypes = [XIC] XSetICFocus.restype = None Xutf8ResetIC = libX11.Xutf8ResetIC Xutf8ResetIC.argtypes = [XIC] Xutf8ResetIC.restype = String Xutf8LookupString = libX11.Xutf8LookupString Xutf8LookupString.argtypes = [XIC, POINTER(XKeyPressedEvent), String, c_int, POINTER(KeySym), POINTER(c_int)] Xutf8LookupString.restype = c_int XKeysymToString = libX11.XKeysymToString XKeysymToString.argtypes = [KeySym] XKeysymToString.restype = String XkbKeycodeToKeysym = libX11.XkbKeycodeToKeysym XkbKeycodeToKeysym.argtypes = [POINTER(Display), KeyCode, c_uint, c_uint] XkbKeycodeToKeysym.restype = KeySym ## record extensions libXtst = CDLL('libXtst.so.6') # types XPointer = String XRecordContext = c_ulong XRecordClientSpec = c_ulong class XRecordRange8(Structure): _fields_ = [('first', c_ubyte), ('last', c_ubyte)] class XRecordRange16(Structure): _fields_ = [('first', c_ushort), ('last', c_ushort)] class XRecordExtRange(Structure): _fields_ = [('ext_major', XRecordRange8), ('ext_minor', XRecordRange16)] class XRecordRange(Structure): _fields_ = [('core_requests', XRecordRange8), ('core_replies', XRecordRange8), ('ext_requests', XRecordExtRange), ('ext_replies', XRecordExtRange), ('delivered_events', XRecordRange8), ('device_events', XRecordRange8), ('errors', XRecordRange8), ('client_started', c_int), ('client_died', c_int)] class XRecordInterceptData(Structure): _fields_ = [('id_base', XID), ('server_time', Time), ('client_seq', c_ulong), ('category', c_int), ('client_swapped', c_int), ('data', POINTER(c_ubyte)), ('data_len', c_ulong)] XRecordInterceptProc = CFUNCTYPE(None, XPointer, POINTER(XRecordInterceptData)) # constants XRecordAllClients = 3 XRecordFromServer = 0 # functions XRecordAllocRange = libXtst.XRecordAllocRange XRecordAllocRange.argtypes = [] XRecordAllocRange.restype = POINTER(XRecordRange) XRecordCreateContext = libXtst.XRecordCreateContext XRecordCreateContext.argtypes = [POINTER(Display), c_int, POINTER(XRecordClientSpec), c_int, POINTER(POINTER(XRecordRange)), c_int] XRecordCreateContext.restype = XRecordContext XRecordEnableContextAsync = libXtst.XRecordEnableContextAsync XRecordEnableContextAsync.argtypes = [POINTER(Display), XRecordContext, XRecordInterceptProc, XPointer] XRecordEnableContextAsync.restype = c_int XRecordProcessReplies = libXtst.XRecordProcessReplies XRecordProcessReplies.argtypes = [POINTER(Display)] XRecordProcessReplies.restype = None XRecordDisableContext = libXtst.XRecordDisableContext XRecordDisableContext.argtypes = [POINTER(Display), XRecordContext] XRecordDisableContext.restype = c_int XRecordFreeContext = libXtst.XRecordFreeContext XRecordFreeContext.argtypes = [POINTER(Display), XRecordContext] XRecordFreeContext.restype = c_int XRecordFreeData = libXtst.XRecordFreeData XRecordFreeData.argtypes = [POINTER(XRecordInterceptData)] XRecordFreeData.restype = None ## wire protocol CARD8 = c_ubyte CARD16 = c_ushort CARD32 = c_uint BOOL = CARD8 BYTE = CARD8 INT16 = c_short class xEventType(Structure): _fields_ = [('type', BYTE), ('detail', BYTE), ('sequenceNumber', CARD16)] class xKeyButtonPointer(Structure): _fields_ = [('pad00', CARD32), ('time', CARD32), ('root', CARD32), ('event', CARD32), ('child', CARD32), ('rootX', INT16), ('rootY', INT16), ('eventX', INT16), ('eventY', INT16), ('state', CARD16), ('sameScreen', BOOL), ('pad1', BYTE)] class xEvent(Union): _fields_ = [('u', xEventType), ('keyButtonPointer', xKeyButtonPointer)] def _kbd_wire_to_event(dpy, wev): ev = XEvent() ev.xkey.type = wev.u.type ev.xkey.serial = wev.u.sequenceNumber ev.xkey.send_event = ((wev.u.type & 0x80) != 0) ev.xkey.display = dpy ev.xkey.window = wev.keyButtonPointer.event ev.xkey.root = wev.keyButtonPointer.root ev.xkey.subwindow = wev.keyButtonPointer.child ev.xkey.time = wev.keyButtonPointer.time ev.xkey.x = wev.keyButtonPointer.eventX ev.xkey.y = wev.keyButtonPointer.eventY ev.xkey.x_root = wev.keyButtonPointer.rootX ev.xkey.y_root = wev.keyButtonPointer.rootY ev.xkey.state = wev.keyButtonPointer.state ev.xkey.keycode = wev.u.detail ev.xkey.same_screen = wev.keyButtonPointer.sameScreen return ev def _btn_wire_to_event(dpy, wev): ev = XEvent() ev.xbutton.type = wev.u.type ev.xbutton.serial = wev.u.sequenceNumber ev.xbutton.send_event = ((wev.u.type & 0x80) != 0) ev.xbutton.display = dpy ev.xbutton.window = wev.keyButtonPointer.event ev.xbutton.root = wev.keyButtonPointer.root ev.xbutton.subwindow = wev.keyButtonPointer.child ev.xbutton.time = wev.keyButtonPointer.time ev.xbutton.x = wev.keyButtonPointer.eventX ev.xbutton.y = wev.keyButtonPointer.eventY ev.xbutton.x_root = wev.keyButtonPointer.rootX ev.xbutton.y_root = wev.keyButtonPointer.rootY ev.xbutton.state = wev.keyButtonPointer.state ev.xbutton.button = wev.u.detail ev.xbutton.same_screen = wev.keyButtonPointer.sameScreen return ev def _mtn_wire_to_event(dpy, wev): ev = XEvent() ev.xmotion.type = wev.u.type ev.xmotion.serial = wev.u.sequenceNumber ev.xmotion.send_event = ((wev.u.type & 0x80) != 0) ev.xmotion.display = dpy ev.xmotion.window = wev.keyButtonPointer.event ev.xmotion.root = wev.keyButtonPointer.root ev.xmotion.subwindow = wev.keyButtonPointer.child ev.xmotion.time = wev.keyButtonPointer.time ev.xmotion.x = wev.keyButtonPointer.eventX ev.xmotion.y = wev.keyButtonPointer.eventY ev.xmotion.x_root = wev.keyButtonPointer.rootX ev.xmotion.y_root = wev.keyButtonPointer.rootY ev.xmotion.state = wev.keyButtonPointer.state ev.xmotion.is_hint = wev.u.detail ev.xmotion.same_screen = wev.keyButtonPointer.sameScreen return ev def XWireToEvent(dpy, data): # this could have been avoided if _XWireToEvent didn't have internal state wev = cast(data, POINTER(xEvent)).contents if wev.u.type in [KeyPress, KeyRelease]: return _kbd_wire_to_event(dpy, wev) elif wev.u.type in [ButtonPress, ButtonRelease]: return _btn_wire_to_event(dpy, wev) elif wev.u.type == MotionNotify: return _mtn_wire_to_event(dpy, wev) return XEvent(wev.u.type) screenkey-v1.5/data/000077500000000000000000000000001415444532700144575ustar00rootroot00000000000000screenkey-v1.5/data/org.thregr.screenkey.metainfo.xml000066400000000000000000000016011415444532700230500ustar00rootroot00000000000000 org.thregr.screenkey Screenkey Screencast your keystrokes CC-BY-SA-4.0 GPL-3.0-or-later

A screencast tool to display your keys.

screenkey.desktop Screenkey in action https://www.thregr.org/~wavexx/software/screenkey/screenkey.gif https://www.thregr.org/~wavexx/software/screenkey/ screenkey
screenkey-v1.5/data/screenkey.desktop000066400000000000000000000002501415444532700200370ustar00rootroot00000000000000[Desktop Entry] Version=1.0 Type=Application Name=Screenkey Comment=Screencast your keys Exec=screenkey Icon=preferences-desktop-keyboard-shortcuts Categories=Utility; screenkey-v1.5/screenkey000077500000000000000000000123431415444532700154670ustar00rootroot00000000000000#!/usr/bin/env python3 # "screenkey" is distributed under GNU GPLv3+, WITHOUT ANY WARRANTY. # Copyright(c) 2010-2012: Pablo Seminario # Copyright(c) 2015-2020: wave++ "Yuri D'Elia" . from Screenkey import * import logging import os import re from argparse import ArgumentParser def parse_geom_fract(buf): if len(buf) == 0: return 0 if buf[-1] == '%': v = int(buf[:-1]) if v == 0: return 0 return v / 100 return int(buf) def geometry(string): size = re.match(r'^(\d+%?)x(\d+%?)(?:([+-]\d+%?)([+-]\d+%?))?$', string) if size is None: raise TypeError w = parse_geom_fract(size.group(1)) h = parse_geom_fract(size.group(2)) if w == 0 or h == 0: raise TypeError x = parse_geom_fract(size.group(3)) if size.group(3) else 0 y = parse_geom_fract(size.group(4)) if size.group(4) else 0 return [x, y, w, h] def main(): ap = ArgumentParser(description=APP_DESC) ap.add_argument("-d", "--debug", action="store_true", help=_("enable debugging")) ap.add_argument("--no-systray", action="store_true", help=_("do not create system tray icon")) ap.add_argument("-t", "--timeout", type=float, help=_("timeout in seconds")) ap.add_argument("-p", "--position", choices=POSITIONS, help=_("set vertical position")) ap.add_argument("--persist", action='store_true', default=None, help=_("make window persistent")) ap.add_argument("--window", action='store_true', default=None, help=_("use a regular window for display (implies --persist)")) ap.add_argument("-s", "--font-size", choices=FONT_SIZES, help=_("set font size")) ap.add_argument("-g", "--geometry", type=geometry, help=_("set fixed area/window geometry")) ap.add_argument("--key-mode", choices=KEY_MODES, help=_("set key processing mode")) ap.add_argument("--bak-mode", choices=BAK_MODES, help=_("backspace processing mode")) ap.add_argument("--mods-mode", choices=MODS_MODES, help=_("modifiers visualization mode")) ap.add_argument("-m", "--mods-only", action="store_true", default=None, help=_("show only keys with modifiers pressed")) ap.add_argument("--multiline", action="store_true", default=None, help=_("span text over multiple lines")) ap.add_argument("--vis-shift", action="store_true", default=None, help=_("always show Shift when modifiers are pressed")) ap.add_argument("--no-whitespace", dest='vis_space', action="store_false", default=None, help=_("disable visualization of whitespace")) ap.add_argument("--show-settings", action="store_true", help=_("show settings dialog on start")) ap.add_argument("--scr", dest='screen', type=int, help=_("show on the specified screen number")) ap.add_argument("-f", "--font", dest='font_desc', help=_("set font family/weight")) ap.add_argument("--font-color", dest='font_color', help=_("set font color")) ap.add_argument("--bg-color", dest='bg_color', help=_("background color")) ap.add_argument("--opacity", dest='opacity', type=float, help=_("window opacity (in range 0.0-1.0)")) ap.add_argument("--ignore", action='append', metavar='KeySym', default=[], help=_("Ignore the specified KeySym")) ap.add_argument("--compr-cnt", type=int, metavar='COUNT', help=_("Compress key repeats after the specified count")) ap.add_argument("--start-disabled", action='store_true', default=None, help=_("do not display anything until explicitly requested")) ap.add_argument('--version', action='version', version=VERSION, help=_("show version of screenkey")) ap.add_argument("-M", "--mouse", action="store_true", default=None, help=_("show the mouse buttons")) ap.add_argument("--mouse-fade", type=float, dest='button_hide_duration', help=_("Mouse buttons fade duration in seconds")) args = ap.parse_args() # Set options options = Options() for arg in ['timeout', 'position', 'persist', 'window', 'font_desc', 'font_color', 'bg_color', 'font_size', 'geometry', 'key_mode', 'bak_mode', 'mods_mode', 'mods_only', 'multiline', 'vis_shift', 'vis_space', 'screen', 'no_systray', 'opacity', 'ignore', 'compr_cnt', 'start_disabled', 'mouse', 'button_hide_duration']: if getattr(args, arg) is not None: options[arg] = getattr(args, arg) # Initialize logger if args.debug: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) logger = logging.getLogger(APP_NAME) import Screenkey.screenkey as sc app = sc.Screenkey(logger=logger, options=options, show_settings=args.show_settings) try: exit(app.run()) except KeyboardInterrupt: os._exit(0) if __name__ == "__main__": main() screenkey-v1.5/setup.cfg000066400000000000000000000006061415444532700153710ustar00rootroot00000000000000[extract_messages] input_dirs = Screenkey output_file = Screenkey/locale/screenkey.pot [init_catalog] domain = screenkey input_file = Screenkey/locale/screenkey.pot output_dir = Screenkey/locale [update_catalog] domain = screenkey input_file = Screenkey/locale/screenkey.pot output_dir = Screenkey/locale previous = true [compile_catalog] domain = screenkey directory = Screenkey/locale screenkey-v1.5/setup.py000077500000000000000000000036331415444532700152700ustar00rootroot00000000000000#!/usr/bin/env python3 from setuptools import setup from distutils.command.build import build class BuildWithCompile(build): sub_commands = [('compile_catalog', None)] + build.sub_commands setup(name='screenkey', version='1.5', description='A screencast tool to display keys', author='Pablo Seminario', author_email='pabluk@gmail.com', maintainer='Yuri D\'Elia', maintainer_email='wavexx@thregr.org', license='GPLv3+', keywords='screencast keyboard presentation keys', url='http://www.thregr.org/~wavexx/software/screenkey/', classifiers=['Development Status :: 5 - Production/Stable', 'Environment :: X11 Applications :: GTK', 'Intended Audience :: Education', 'Intended Audience :: End Users/Desktop', 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', 'Operating System :: POSIX', 'Operating System :: Unix', 'Topic :: Education', 'Topic :: Multimedia :: Graphics :: Presentation', 'Topic :: Multimedia :: Video :: Capture'], long_description=""" Screenkey is a useful tool for presentations or screencasts. Inspired by ScreenFlick and initially based on the key-mon project code. """, scripts=['screenkey'], packages=['Screenkey'], setup_requires=['setuptools', 'babel'], install_requires=['PyGObject', 'pycairo', 'dbus-python'], package_data={'': [ 'images/mouse.svg', 'locale/*/LC_MESSAGES/screenkey.mo' ]}, data_files=[ ('share/applications', ['data/screenkey.desktop']), ('share/doc/screenkey', ['README.rst', 'NEWS.rst']), ('share/metainfo', ['data/org.thregr.screenkey.metainfo.xml']) ], cmdclass={ 'build': BuildWithCompile, }, )