pax_global_header 0000666 0000000 0000000 00000000064 14154445327 0014523 g ustar 00root root 0000000 0000000 52 comment=855b64d2bd92e9f570e55886c163fa15972269fd
screenkey-v1.5/ 0000775 0000000 0000000 00000000000 14154445327 0013546 5 ustar 00root root 0000000 0000000 screenkey-v1.5/.gitignore 0000664 0000000 0000000 00000000073 14154445327 0015536 0 ustar 00root root 0000000 0000000 *[#~]
*.py[co]
/*.egg-info
/.eggs/
*.pot
*.mo
/dist
/build
screenkey-v1.5/COPYING.txt 0000664 0000000 0000000 00000104513 14154445327 0015423 0 ustar 00root root 0000000 0000000 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.rst 0000664 0000000 0000000 00000013304 14154445327 0015055 0 ustar 00root root 0000000 0000000 screenkey 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.rst 0000664 0000000 0000000 00000043303 14154445327 0015240 0 ustar 00root root 0000000 0000000 =====================
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/ 0000775 0000000 0000000 00000000000 14154445327 0015476 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/__init__.py 0000664 0000000 0000000 00000003454 14154445327 0017615 0 ustar 00root root 0000000 0000000 try:
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/ 0000775 0000000 0000000 00000000000 14154445327 0016743 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/images/mouse.original.svg 0000664 0000000 0000000 00000033350 14154445327 0022423 0 ustar 00root root 0000000 0000000
screenkey-v1.5/Screenkey/images/mouse.svg 0000664 0000000 0000000 00000012400 14154445327 0020611 0 ustar 00root root 0000000 0000000
screenkey-v1.5/Screenkey/inputlistener.py 0000664 0000000 0000000 00000036672 14154445327 0020773 0 ustar 00root root 0000000 0000000 # 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.py 0000664 0000000 0000000 00000236125 14154445327 0017565 0 ustar 00root root 0000000 0000000 # 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.py 0000664 0000000 0000000 00000063726 14154445327 0020500 0 ustar 00root root 0000000 0000000 # "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/ 0000775 0000000 0000000 00000000000 14154445327 0016735 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/ca/ 0000775 0000000 0000000 00000000000 14154445327 0017320 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/ca/LC_MESSAGES/ 0000775 0000000 0000000 00000000000 14154445327 0021105 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/ca/LC_MESSAGES/screenkey.po 0000664 0000000 0000000 00000034146 14154445327 0023445 0 ustar 00root root 0000000 0000000 # 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}"
"a>"
msgstr ""
"Cal l'\"slop\" per a la selecció interactiva. Vegeu {url}"
"a>"
#: ../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/ 0000775 0000000 0000000 00000000000 14154445327 0017325 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/de/LC_MESSAGES/ 0000775 0000000 0000000 00000000000 14154445327 0021112 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/de/LC_MESSAGES/screenkey.po 0000664 0000000 0000000 00000026476 14154445327 0023461 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 14154445327 0017344 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/es/LC_MESSAGES/ 0000775 0000000 0000000 00000000000 14154445327 0021131 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/es/LC_MESSAGES/screenkey.po 0000664 0000000 0000000 00000004017 14154445327 0023463 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 14154445327 0017344 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/fr/LC_MESSAGES/ 0000775 0000000 0000000 00000000000 14154445327 0021131 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/fr/LC_MESSAGES/screenkey.po 0000664 0000000 0000000 00000026131 14154445327 0023464 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 14154445327 0017363 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/ru/LC_MESSAGES/ 0000775 0000000 0000000 00000000000 14154445327 0021150 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/ru/LC_MESSAGES/screenkey.po 0000664 0000000 0000000 00000037257 14154445327 0023516 0 ustar 00root root 0000000 0000000 # 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}"
"a>"
msgstr ""
"Для интерактивного выделения требуется «slop». Подробнее: {url}"
"a>"
#: ../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/ 0000775 0000000 0000000 00000000000 14154445327 0017354 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/uk/LC_MESSAGES/ 0000775 0000000 0000000 00000000000 14154445327 0021141 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/uk/LC_MESSAGES/screenkey.po 0000664 0000000 0000000 00000005374 14154445327 0023502 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 14154445327 0017736 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/zh_CN/LC_MESSAGES/ 0000775 0000000 0000000 00000000000 14154445327 0021523 5 ustar 00root root 0000000 0000000 screenkey-v1.5/Screenkey/locale/zh_CN/LC_MESSAGES/screenkey.po 0000664 0000000 0000000 00000034752 14154445327 0024066 0 ustar 00root root 0000000 0000000 # 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}"
"a>"
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.py 0000664 0000000 0000000 00000124252 14154445327 0020046 0 ustar 00root root 0000000 0000000 # "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.py 0000664 0000000 0000000 00000031763 14154445327 0017020 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 14154445327 0014457 5 ustar 00root root 0000000 0000000 screenkey-v1.5/data/org.thregr.screenkey.metainfo.xml 0000664 0000000 0000000 00000001601 14154445327 0023050 0 ustar 00root root 0000000 0000000
org.thregr.screenkeyScreenkeyScreencast your keystrokesCC-BY-SA-4.0GPL-3.0-or-later
A screencast tool to display your keys.
screenkey.desktop
Screenkey in action
https://www.thregr.org/~wavexx/software/screenkey/screenkey.gifhttps://www.thregr.org/~wavexx/software/screenkey/screenkey
screenkey-v1.5/data/screenkey.desktop 0000664 0000000 0000000 00000000250 14154445327 0020037 0 ustar 00root root 0000000 0000000 [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/screenkey 0000775 0000000 0000000 00000012343 14154445327 0015467 0 ustar 00root root 0000000 0000000 #!/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.cfg 0000664 0000000 0000000 00000000606 14154445327 0015371 0 ustar 00root root 0000000 0000000 [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.py 0000775 0000000 0000000 00000003633 14154445327 0015270 0 ustar 00root root 0000000 0000000 #!/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,
},
)