mirror of
https://github.com/go-vgo/robotgo.git
synced 2025-05-30 22:13:54 +00:00
update vendor pkg to newest
This commit is contained in:
parent
75b468839f
commit
3d65e37f98
10
Gopkg.lock
generated
10
Gopkg.lock
generated
@ -50,6 +50,12 @@
|
||||
revision = "b026a6fd291f00736db60738f4e83a79d26359cb"
|
||||
version = "v2.2.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/robotn/gohook"
|
||||
packages = ["."]
|
||||
revision = "3dccbf0083168096c576bf62abb3d5d4c916e2ea"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/shirou/gopsutil"
|
||||
packages = [
|
||||
@ -88,11 +94,11 @@
|
||||
"unix",
|
||||
"windows"
|
||||
]
|
||||
revision = "49385e6e15226593f68b26af201feec29d5bba22"
|
||||
revision = "d0be0721c37eeb5299f245a996a483160fc36940"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "0fd06dbf29cbad04968ef5a7c12e61c18ab8595bcb2d30c9f35698f0873916d1"
|
||||
inputs-digest = "b1299bcf48c5b674a219acd0d53d6e1dc9cd44f60a9448f74d2fb623eaf9b00a"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
@ -1 +1 @@
|
||||
C language dependent package, better to compilation. You need to follow the relevant agreement and LICENSE.
|
||||
C language dependent package, better to compilation.
|
24
vendor/github.com/robotn/gohook/.gitignore
generated
vendored
Normal file
24
vendor/github.com/robotn/gohook/.gitignore
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
674
vendor/github.com/robotn/gohook/LICENSE
generated
vendored
Normal file
674
vendor/github.com/robotn/gohook/LICENSE
generated
vendored
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
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.
|
||||
|
||||
{one line to give the program's name and a brief idea of what it does.}
|
||||
Copyright (C) {year} {name of author}
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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:
|
||||
|
||||
{project} Copyright (C) {year} {fullname}
|
||||
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
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
21
vendor/github.com/robotn/gohook/README.md
generated
vendored
Normal file
21
vendor/github.com/robotn/gohook/README.md
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# gohook
|
||||
|
||||
This is a work in progress.
|
||||
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go-vgo/robotn/gohook"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// hook.AsyncHook()
|
||||
veve := hook.AddEvent("v")
|
||||
if veve == 0 {
|
||||
fmt.Println("v...")
|
||||
}
|
||||
}
|
||||
```
|
252
vendor/github.com/robotn/gohook/event/goEvent.h
generated
vendored
Normal file
252
vendor/github.com/robotn/gohook/event/goEvent.h
generated
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pub.h"
|
||||
|
||||
|
||||
void dispatch_proc(iohook_event * const event) {
|
||||
char buffer[256] = { 0 };
|
||||
size_t length = snprintf(buffer, sizeof(buffer),
|
||||
"id=%i,when=%" PRIu64 ",mask=0x%X",
|
||||
event->type, event->time, event->mask);
|
||||
|
||||
switch (event->type) {
|
||||
case EVENT_KEY_PRESSED:
|
||||
// If the escape key is pressed, naturally terminate the program.
|
||||
if (event->data.keyboard.keycode == VC_ESCAPE) {
|
||||
// int status = hook_stop();
|
||||
// switch (status) {
|
||||
// // System level errors.
|
||||
// case IOHOOK_ERROR_OUT_OF_MEMORY:
|
||||
// loggerProc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)", status);
|
||||
// break;
|
||||
|
||||
// case IOHOOK_ERROR_X_RECORD_GET_CONTEXT:
|
||||
// // NOTE This is the only platform specific error that occurs on hook_stop().
|
||||
// loggerProc(LOG_LEVEL_ERROR, "Failed to get XRecord context. (%#X)", status);
|
||||
// break;
|
||||
|
||||
// // Default error.
|
||||
// case IOHOOK_FAILURE:
|
||||
// default:
|
||||
// loggerProc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)", status);
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
case EVENT_KEY_RELEASED:
|
||||
snprintf(buffer + length, sizeof(buffer) - length,
|
||||
",keycode=%u,rawcode=0x%X",
|
||||
event->data.keyboard.keycode, event->data.keyboard.rawcode);
|
||||
int akeyCode = (uint16_t) event->data.keyboard.keycode;
|
||||
|
||||
if (event->data.keyboard.keycode == VC_ESCAPE
|
||||
&& atoi(cevent) == 11) {
|
||||
int stopEvent = stop_event();
|
||||
// printf("stop_event%d\n", stopEvent);
|
||||
cstatus = 0;
|
||||
}
|
||||
|
||||
// printf("atoi(str)---%d\n", atoi(cevent));
|
||||
if (akeyCode == atoi(cevent)) {
|
||||
int stopEvent = stop_event();
|
||||
// printf("%d\n", stopEvent);
|
||||
cstatus = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_KEY_TYPED:
|
||||
snprintf(buffer + length, sizeof(buffer) - length,
|
||||
",keychar=%lc,rawcode=%u",
|
||||
(uint16_t) event->data.keyboard.keychar,
|
||||
event->data.keyboard.rawcode);
|
||||
|
||||
#ifdef WE_REALLY_WANT_A_POINTER
|
||||
char *buf = malloc (6);
|
||||
#else
|
||||
char buf[6];
|
||||
#endif
|
||||
|
||||
sprintf(buf, "%lc", (uint16_t) event->data.keyboard.keychar);
|
||||
|
||||
#ifdef WE_REALLY_WANT_A_POINTER
|
||||
free (buf);
|
||||
#endif
|
||||
|
||||
if (strcmp(buf, cevent) == 0) {
|
||||
int stopEvent = stop_event();
|
||||
// printf("%d\n", stopEvent);
|
||||
cstatus = 0;
|
||||
}
|
||||
// return (char*) event->data.keyboard.keychar;
|
||||
break;
|
||||
|
||||
case EVENT_MOUSE_PRESSED:
|
||||
case EVENT_MOUSE_RELEASED:
|
||||
case EVENT_MOUSE_CLICKED:
|
||||
case EVENT_MOUSE_MOVED:
|
||||
case EVENT_MOUSE_DRAGGED:
|
||||
snprintf(buffer + length, sizeof(buffer) - length,
|
||||
",x=%i,y=%i,button=%i,clicks=%i",
|
||||
event->data.mouse.x, event->data.mouse.y,
|
||||
event->data.mouse.button, event->data.mouse.clicks);
|
||||
|
||||
int abutton = event->data.mouse.button;
|
||||
int aclicks = event->data.mouse.clicks;
|
||||
int amouse = -1;
|
||||
|
||||
if (strcmp(cevent, "mleft") == 0) {
|
||||
amouse = 1;
|
||||
}
|
||||
if (strcmp(cevent, "mright") == 0) {
|
||||
amouse = 2;
|
||||
}
|
||||
if (strcmp(cevent, "wheelDown") == 0) {
|
||||
amouse = 4;
|
||||
}
|
||||
if (strcmp(cevent, "wheelUp") == 0) {
|
||||
amouse = 5;
|
||||
}
|
||||
if (strcmp(cevent, "wheelLeft") == 0) {
|
||||
amouse = 6;
|
||||
}
|
||||
if (strcmp(cevent, "wheelRight") == 0) {
|
||||
amouse = 7;
|
||||
}
|
||||
if (abutton == amouse && aclicks == 1) {
|
||||
int stopEvent = stop_event();
|
||||
cstatus = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EVENT_MOUSE_WHEEL:
|
||||
snprintf(buffer + length, sizeof(buffer) - length,
|
||||
",type=%i,amount=%i,rotation=%i",
|
||||
event->data.wheel.type, event->data.wheel.amount,
|
||||
event->data.wheel.rotation);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// fprintf(stdout, "----%s\n", buffer);
|
||||
}
|
||||
|
||||
int add_event(char *key_event) {
|
||||
// (uint16_t *)
|
||||
cevent = key_event;
|
||||
// Set the logger callback for library output.
|
||||
hookSetlogger(&loggerProc);
|
||||
|
||||
// Set the event callback for IOhook events.
|
||||
hook_set_dispatch_proc(&dispatch_proc);
|
||||
// Start the hook and block.
|
||||
// NOTE If EVENT_HOOK_ENABLED was delivered, the status will always succeed.
|
||||
int status = hook_run();
|
||||
|
||||
switch (status) {
|
||||
case IOHOOK_SUCCESS:
|
||||
// Everything is ok.
|
||||
break;
|
||||
|
||||
// System level errors.
|
||||
case IOHOOK_ERROR_OUT_OF_MEMORY:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)", status);
|
||||
break;
|
||||
|
||||
|
||||
// X11 specific errors.
|
||||
case IOHOOK_ERROR_X_OPEN_DISPLAY:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to open X11 display. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_X_RECORD_NOT_FOUND:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Unable to locate XRecord extension. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_X_RECORD_ALLOC_RANGE:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Unable to allocate XRecord range. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_X_RECORD_CREATE_CONTEXT:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Unable to allocate XRecord context. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_X_RECORD_ENABLE_CONTEXT:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to enable XRecord context. (%#X)", status);
|
||||
break;
|
||||
|
||||
|
||||
// Windows specific errors.
|
||||
case IOHOOK_ERROR_SET_WINDOWS_HOOK_EX:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to register low level windows hook. (%#X)", status);
|
||||
break;
|
||||
|
||||
|
||||
// Darwin specific errors.
|
||||
case IOHOOK_ERROR_AXAPI_DISABLED:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to enable access for assistive devices. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_CREATE_EVENT_PORT:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to create apple event port. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_CREATE_RUN_LOOP_SOURCE:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to create apple run loop source. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_GET_RUNLOOP:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to acquire apple run loop. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_CREATE_OBSERVER:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to create apple run loop observer. (%#X)", status);
|
||||
break;
|
||||
|
||||
// Default error.
|
||||
case IOHOOK_FAILURE:
|
||||
default:
|
||||
loggerProc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)", status);
|
||||
break;
|
||||
}
|
||||
|
||||
// return status;
|
||||
// printf("%d\n", status);
|
||||
return cstatus;
|
||||
}
|
||||
|
||||
int stop_event(){
|
||||
int status = hook_stop();
|
||||
switch (status) {
|
||||
// System level errors.
|
||||
case IOHOOK_ERROR_OUT_OF_MEMORY:
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)", status);
|
||||
break;
|
||||
|
||||
case IOHOOK_ERROR_X_RECORD_GET_CONTEXT:
|
||||
// NOTE This is the only platform specific error that occurs on hook_stop().
|
||||
loggerProc(LOG_LEVEL_ERROR, "Failed to get XRecord context. (%#X)", status);
|
||||
break;
|
||||
|
||||
// Default error.
|
||||
case IOHOOK_FAILURE:
|
||||
default:
|
||||
// loggerProc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)", status);
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
49
vendor/github.com/robotn/gohook/event/os.h
generated
vendored
Normal file
49
vendor/github.com/robotn/gohook/event/os.h
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
#ifndef OS_H
|
||||
#define OS_H
|
||||
|
||||
/* Python versions under 2.5 don't support this macro, but it's not
|
||||
* terribly difficult to replicate: */
|
||||
#ifndef PyModule_AddIntMacro
|
||||
#define PyModule_AddIntMacro(module, macro) \
|
||||
PyModule_AddIntConstant(module, #macro, macro)
|
||||
#endif /* PyModule_AddIntMacro */
|
||||
|
||||
#if !defined(IS_MACOSX) && defined(__APPLE__) && defined(__MACH__)
|
||||
#define IS_MACOSX
|
||||
#endif /* IS_MACOSX */
|
||||
|
||||
#if !defined(IS_WINDOWS) && (defined(WIN32) || defined(_WIN32) || \
|
||||
defined(__WIN32__) || defined(__WINDOWS__) || defined(__CYGWIN__))
|
||||
#define IS_WINDOWS
|
||||
#endif /* IS_WINDOWS */
|
||||
|
||||
#if !defined(USE_X11) && !defined(NUSE_X11) && !defined(IS_MACOSX) && !defined(IS_WINDOWS)
|
||||
#define USE_X11
|
||||
#endif /* USE_X11 */
|
||||
|
||||
#if defined(IS_WINDOWS)
|
||||
#define STRICT /* Require use of exact types. */
|
||||
#define WIN32_LEAN_AND_MEAN 1 /* Speed up compilation. */
|
||||
#include <windows.h>
|
||||
#elif !defined(IS_MACOSX) && !defined(USE_X11)
|
||||
#error "Sorry, this platform isn't supported yet!"
|
||||
#endif
|
||||
|
||||
/* Interval to align by for large buffers (e.g. bitmaps). */
|
||||
/* Must be a power of 2. */
|
||||
#ifndef BYTE_ALIGN
|
||||
#define BYTE_ALIGN 4 /* Bytes to align pixel buffers to. */
|
||||
/* #include <stddef.h> */
|
||||
/* #define BYTE_ALIGN (sizeof(size_t)) */
|
||||
#endif /* BYTE_ALIGN */
|
||||
|
||||
#if BYTE_ALIGN == 0
|
||||
/* No alignment needed. */
|
||||
#define ADD_PADDING(width) (width)
|
||||
#else
|
||||
/* Aligns given width to padding. */
|
||||
#define ADD_PADDING(width) (BYTE_ALIGN + (((width) - 1) & ~(BYTE_ALIGN - 1)))
|
||||
#endif
|
||||
|
||||
#endif /* OS_H */
|
95
vendor/github.com/robotn/gohook/event/pub.h
generated
vendored
Normal file
95
vendor/github.com/robotn/gohook/event/pub.h
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#include "os.h"
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
#include "../hook/darwin/input_c.h"
|
||||
#include "../hook/darwin/hook_c.h"
|
||||
#include "../hook/darwin/event_c.h"
|
||||
#include "../hook/darwin/properties_c.h"
|
||||
#elif defined(USE_X11)
|
||||
//#define USE_XKBCOMMON 0
|
||||
#include "../hook/x11/input_c.h"
|
||||
#include "../hook/x11/hook_c.h"
|
||||
#include "../hook/x11/event_c.h"
|
||||
#include "../hook/x11/properties_c.h"
|
||||
#elif defined(IS_WINDOWS)
|
||||
#include "../hook/windows/input_c.h"
|
||||
#include "../hook/windows/hook_c.h"
|
||||
#include "../hook/windows/event_c.h"
|
||||
#include "../hook/windows/properties_c.h"
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../hook/iohook.h"
|
||||
|
||||
|
||||
int vccode[100];
|
||||
int codesz;
|
||||
|
||||
char *cevent;
|
||||
int rrevent;
|
||||
// uint16_t *cevent;
|
||||
int cstatus = 1;
|
||||
|
||||
|
||||
int stop_event();
|
||||
int add_event(char *key_event);
|
||||
// int allEvent(char *key_event);
|
||||
int allEvent(char *key_event, int vcode[], int size);
|
||||
|
||||
// NOTE: The following callback executes on the same thread that hook_run() is called
|
||||
// from.
|
||||
|
||||
struct _MEvent {
|
||||
uint8_t id;
|
||||
size_t mask;
|
||||
uint16_t keychar;
|
||||
// char *keychar;
|
||||
size_t x;
|
||||
uint8_t y;
|
||||
uint8_t bytesPerPixel;
|
||||
};
|
||||
|
||||
typedef struct _MEvent MEvent;
|
||||
// typedef MMBitmap *MMBitmapRef;
|
||||
|
||||
MEvent mEvent;
|
||||
|
||||
|
||||
bool loggerProc(unsigned int level, const char *format, ...) {
|
||||
bool status = false;
|
||||
|
||||
va_list args;
|
||||
switch (level) {
|
||||
#ifdef USE_DEBUG
|
||||
case LOG_LEVEL_DEBUG:
|
||||
case LOG_LEVEL_INFO:
|
||||
va_start(args, format);
|
||||
status = vfprintf(stdout, format, args) >= 0;
|
||||
va_end(args);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case LOG_LEVEL_WARN:
|
||||
case LOG_LEVEL_ERROR:
|
||||
va_start(args, format);
|
||||
status = vfprintf(stderr, format, args) >= 0;
|
||||
va_end(args);
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
35
vendor/github.com/robotn/gohook/hook.go
generated
vendored
Normal file
35
vendor/github.com/robotn/gohook/hook.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package hook
|
||||
|
||||
/*
|
||||
#cgo darwin CFLAGS: -x objective-c -Wno-deprecated-declarations
|
||||
#cgo darwin LDFLAGS: -framework Cocoa
|
||||
#cgo linux CFLAGS:-I/usr/src
|
||||
#cgo linux LDFLAGS: -L/usr/src -lX11 -lXtst
|
||||
#cgo linux LDFLAGS: -lX11-xcb -lxcb -lxcb-xkb -lxkbcommon -lxkbcommon-x11
|
||||
#cgo windows LDFLAGS: -lgdi32 -luser32
|
||||
|
||||
#include "event/goEvent.h"
|
||||
// #include "event/hook_async.h"
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import(
|
||||
// "fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// AddEvent add event listener
|
||||
func AddEvent(key string) int {
|
||||
cs := C.CString(key)
|
||||
|
||||
eve := C.add_event(cs)
|
||||
geve := int(eve)
|
||||
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
return geve
|
||||
}
|
||||
|
||||
// StopEvent stop event listener
|
||||
func StopEvent() {
|
||||
C.stop_event()
|
||||
}
|
235
vendor/github.com/robotn/gohook/hook/darwin/event_c.h
generated
vendored
Normal file
235
vendor/github.com/robotn/gohook/hook/darwin/event_c.h
generated
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "../iohook.h"
|
||||
|
||||
// #include "../logger_c.h"
|
||||
#include "input.h"
|
||||
|
||||
// TODO Possibly relocate to input helper.
|
||||
static inline CGEventFlags get_key_event_mask(iohook_event * const event) {
|
||||
CGEventFlags native_mask = 0x00;
|
||||
|
||||
if (event->mask & (MASK_SHIFT)) { native_mask |= kCGEventFlagMaskShift; }
|
||||
if (event->mask & (MASK_CTRL)) { native_mask |= kCGEventFlagMaskControl; }
|
||||
if (event->mask & (MASK_META)) { native_mask |= kCGEventFlagMaskControl; }
|
||||
if (event->mask & (MASK_ALT)) { native_mask |= kCGEventFlagMaskAlternate; }
|
||||
|
||||
if (event->type == EVENT_KEY_PRESSED || event->type == EVENT_KEY_RELEASED || event->type == EVENT_KEY_TYPED) {
|
||||
switch (event->data.keyboard.keycode) {
|
||||
case VC_KP_0:
|
||||
case VC_KP_1:
|
||||
case VC_KP_2:
|
||||
case VC_KP_3:
|
||||
case VC_KP_4:
|
||||
case VC_KP_5:
|
||||
case VC_KP_6:
|
||||
case VC_KP_7:
|
||||
case VC_KP_8:
|
||||
case VC_KP_9:
|
||||
|
||||
case VC_NUM_LOCK:
|
||||
case VC_KP_ENTER:
|
||||
case VC_KP_MULTIPLY:
|
||||
case VC_KP_ADD:
|
||||
case VC_KP_SEPARATOR:
|
||||
case VC_KP_SUBTRACT:
|
||||
case VC_KP_DIVIDE:
|
||||
case VC_KP_COMMA:
|
||||
native_mask |= kCGEventFlagMaskNumericPad;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return native_mask;
|
||||
}
|
||||
|
||||
static inline void post_key_event(iohook_event * const event) {
|
||||
bool is_pressed = event->type == EVENT_KEY_PRESSED;
|
||||
|
||||
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef cg_event = CGEventCreateKeyboardEvent(src,
|
||||
(CGKeyCode) scancode_to_keycode(event->data.keyboard.keycode),
|
||||
is_pressed);
|
||||
|
||||
CGEventSetFlags(cg_event, get_key_event_mask(event));
|
||||
CGEventPost(kCGHIDEventTap, cg_event); // kCGSessionEventTap also works.
|
||||
CFRelease(cg_event);
|
||||
CFRelease(src);
|
||||
}
|
||||
|
||||
static inline void post_mouse_button_event(iohook_event * const event, bool is_pressed) {
|
||||
CGMouseButton mouse_button;
|
||||
CGEventType mouse_type;
|
||||
if (event->data.mouse.button == MOUSE_BUTTON1) {
|
||||
if (is_pressed) {
|
||||
mouse_type = kCGEventLeftMouseDown;
|
||||
}
|
||||
else {
|
||||
mouse_type = kCGEventLeftMouseUp;
|
||||
}
|
||||
mouse_button = kCGMouseButtonLeft;
|
||||
}
|
||||
else if (event->data.mouse.button == MOUSE_BUTTON2) {
|
||||
if (is_pressed) {
|
||||
mouse_type = kCGEventRightMouseDown;
|
||||
}
|
||||
else {
|
||||
mouse_type = kCGEventRightMouseUp;
|
||||
}
|
||||
mouse_button = kCGMouseButtonRight;
|
||||
}
|
||||
else {
|
||||
if (is_pressed) {
|
||||
mouse_type = kCGEventOtherMouseDown;
|
||||
}
|
||||
else {
|
||||
mouse_type = kCGEventOtherMouseUp;
|
||||
}
|
||||
mouse_button = event->data.mouse.button - 1;
|
||||
}
|
||||
|
||||
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef cg_event = CGEventCreateMouseEvent(src,
|
||||
mouse_type,
|
||||
CGPointMake(
|
||||
(CGFloat) event->data.mouse.x,
|
||||
(CGFloat) event->data.mouse.y
|
||||
),
|
||||
mouse_button
|
||||
);
|
||||
CGEventPost(kCGHIDEventTap, cg_event); // kCGSessionEventTap also works.
|
||||
CFRelease(cg_event);
|
||||
CFRelease(src);
|
||||
}
|
||||
|
||||
static inline void post_mouse_wheel_event(iohook_event * const event) {
|
||||
// FIXME Should I create a source event with the coords?
|
||||
// It seems to automagically use the current location of the cursor.
|
||||
// Two options: Query the mouse, move it to x/y, scroll, then move back
|
||||
// OR disable x/y for scroll events on Windows & X11.
|
||||
CGScrollEventUnit scroll_unit;
|
||||
if (event->data.wheel.type == WHEEL_BLOCK_SCROLL) {
|
||||
// Scrolling data is line-based.
|
||||
scroll_unit = kCGScrollEventUnitLine;
|
||||
}
|
||||
else {
|
||||
// Scrolling data is pixel-based.
|
||||
scroll_unit = kCGScrollEventUnitPixel;
|
||||
}
|
||||
|
||||
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef cg_event = CGEventCreateScrollWheelEvent(src,
|
||||
kCGScrollEventUnitLine,
|
||||
// TODO Currently only support 1 wheel axis.
|
||||
(CGWheelCount) 1, // 1 for Y-only, 2 for Y-X, 3 for Y-X-Z
|
||||
event->data.wheel.amount * event->data.wheel.rotation);
|
||||
|
||||
CGEventPost(kCGHIDEventTap, cg_event); // kCGSessionEventTap also works.
|
||||
CFRelease(cg_event);
|
||||
CFRelease(src);
|
||||
}
|
||||
|
||||
static inline void post_mouse_motion_event(iohook_event * const event) {
|
||||
CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef cg_event;
|
||||
if (event->mask >> 8 == 0x00) {
|
||||
// No mouse flags.
|
||||
cg_event = CGEventCreateMouseEvent(src,
|
||||
kCGEventMouseMoved,
|
||||
CGPointMake(
|
||||
(CGFloat) event->data.mouse.x,
|
||||
(CGFloat) event->data.mouse.y
|
||||
),
|
||||
0
|
||||
);
|
||||
}
|
||||
else if (event->mask & MASK_BUTTON1) {
|
||||
cg_event = CGEventCreateMouseEvent(src,
|
||||
kCGEventLeftMouseDragged,
|
||||
CGPointMake(
|
||||
(CGFloat) event->data.mouse.x,
|
||||
(CGFloat) event->data.mouse.y
|
||||
),
|
||||
kCGMouseButtonLeft
|
||||
);
|
||||
}
|
||||
else if (event->mask & MASK_BUTTON2) {
|
||||
cg_event = CGEventCreateMouseEvent(src,
|
||||
kCGEventRightMouseDragged,
|
||||
CGPointMake(
|
||||
(CGFloat) event->data.mouse.x,
|
||||
(CGFloat) event->data.mouse.y
|
||||
),
|
||||
kCGMouseButtonRight
|
||||
);
|
||||
}
|
||||
else {
|
||||
cg_event = CGEventCreateMouseEvent(src,
|
||||
kCGEventOtherMouseDragged,
|
||||
CGPointMake(
|
||||
(CGFloat) event->data.mouse.x,
|
||||
(CGFloat) event->data.mouse.y
|
||||
),
|
||||
(event->mask >> 8) - 1
|
||||
);
|
||||
}
|
||||
|
||||
// kCGSessionEventTap also works.
|
||||
CGEventPost(kCGHIDEventTap, cg_event);
|
||||
CFRelease(cg_event);
|
||||
CFRelease(src);
|
||||
}
|
||||
|
||||
IOHOOK_API void hook_post_event(iohook_event * const event) {
|
||||
switch (event->type) {
|
||||
case EVENT_KEY_PRESSED:
|
||||
case EVENT_KEY_RELEASED:
|
||||
post_key_event(event);
|
||||
break;
|
||||
|
||||
|
||||
case EVENT_MOUSE_PRESSED:
|
||||
post_mouse_button_event(event, true);
|
||||
break;
|
||||
|
||||
case EVENT_MOUSE_RELEASED:
|
||||
post_mouse_button_event(event, false);
|
||||
break;
|
||||
|
||||
case EVENT_MOUSE_CLICKED:
|
||||
post_mouse_button_event(event, true);
|
||||
post_mouse_button_event(event, false);
|
||||
break;
|
||||
|
||||
case EVENT_MOUSE_WHEEL:
|
||||
post_mouse_wheel_event(event);
|
||||
break;
|
||||
|
||||
|
||||
case EVENT_MOUSE_MOVED:
|
||||
case EVENT_MOUSE_DRAGGED:
|
||||
post_mouse_motion_event(event);
|
||||
break;
|
||||
|
||||
|
||||
case EVENT_KEY_TYPED:
|
||||
// FIXME Ignoreing EVENT_KEY_TYPED events.
|
||||
|
||||
case EVENT_HOOK_ENABLED:
|
||||
case EVENT_HOOK_DISABLED:
|
||||
// Ignore hook enabled / disabled events.
|
||||
|
||||
default:
|
||||
// Ignore any other garbage.
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: Ignoring post event type %#X\n",
|
||||
__FUNCTION__, __LINE__, event->type);
|
||||
break;
|
||||
}
|
||||
}
|
1362
vendor/github.com/robotn/gohook/hook/darwin/hook_c.h
generated
vendored
Normal file
1362
vendor/github.com/robotn/gohook/hook/darwin/hook_c.h
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
103
vendor/github.com/robotn/gohook/hook/darwin/input.h
generated
vendored
Normal file
103
vendor/github.com/robotn/gohook/hook/darwin/input.h
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
|
||||
#ifndef _included_input_helper
|
||||
#define _included_input_helper
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <Carbon/Carbon.h> // For HIToolbox kVK_ keycodes and TIS funcitons.
|
||||
#ifdef USE_IOKIT
|
||||
#include <IOKit/hidsystem/ev_keymap.h>
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#ifndef USE_IOKIT
|
||||
// Some of the system key codes that are needed from IOKit.
|
||||
#define NX_KEYTYPE_SOUND_UP 0x00
|
||||
#define NX_KEYTYPE_SOUND_DOWN 0x01
|
||||
#define NX_KEYTYPE_MUTE 0x07
|
||||
|
||||
/* Display controls...
|
||||
#define NX_KEYTYPE_BRIGHTNESS_UP 0x02
|
||||
#define NX_KEYTYPE_BRIGHTNESS_DOWN 0x03
|
||||
#define NX_KEYTYPE_CONTRAST_UP 0x0B
|
||||
#define NX_KEYTYPE_CONTRAST_DOWN 0x0C
|
||||
#define NX_KEYTYPE_ILLUMINATION_UP 0x15
|
||||
#define NX_KEYTYPE_ILLUMINATION_DOWN 0x16
|
||||
#define NX_KEYTYPE_ILLUMINATION_TOGGLE 0x17
|
||||
*/
|
||||
|
||||
#define NX_KEYTYPE_CAPS_LOCK 0x04
|
||||
//#define NX_KEYTYPE_HELP 0x05
|
||||
#define NX_POWER_KEY 0x06
|
||||
|
||||
#define NX_KEYTYPE_EJECT 0x0E
|
||||
#define NX_KEYTYPE_PLAY 0x10
|
||||
#define NX_KEYTYPE_NEXT 0x12
|
||||
#define NX_KEYTYPE_PREVIOUS 0x13
|
||||
|
||||
/* There is no official fast-forward or rewind scan code support.*/
|
||||
#define NX_KEYTYPE_FAST 0x14
|
||||
#define NX_KEYTYPE_REWIND 0x15
|
||||
|
||||
#endif
|
||||
|
||||
// These virtual key codes do not appear to be defined anywhere by Apple.
|
||||
#define kVK_NX_Power 0xE0 | NX_POWER_KEY /* 0xE6 */
|
||||
#define kVK_NX_Eject 0xE0 | NX_KEYTYPE_EJECT /* 0xEE */
|
||||
|
||||
#define kVK_MEDIA_Play 0xE0 | NX_KEYTYPE_PLAY /* 0xF0 */
|
||||
#define kVK_MEDIA_Next 0xE0 | NX_KEYTYPE_NEXT /* 0xF1 */
|
||||
#define kVK_MEDIA_Previous 0xE0 | NX_KEYTYPE_PREVIOUS /* 0xF2 */
|
||||
|
||||
#define kVK_RightCommand 0x36
|
||||
#define kVK_ContextMenu 0x6E // AKA kMenuPowerGlyph
|
||||
#define kVK_Undefined 0xFF
|
||||
|
||||
// These button codes do not appear to be defined anywhere by Apple.
|
||||
#define kVK_LBUTTON kCGMouseButtonLeft
|
||||
#define kVK_RBUTTON kCGMouseButtonRight
|
||||
#define kVK_MBUTTON kCGMouseButtonCenter
|
||||
#define kVK_XBUTTON1 3
|
||||
#define kVK_XBUTTON2 4
|
||||
|
||||
// These button masks do not appear to be defined anywhere by Apple.
|
||||
#define kCGEventFlagMaskButtonLeft 1 << 0
|
||||
#define kCGEventFlagMaskButtonRight 1 << 1
|
||||
#define kCGEventFlagMaskButtonCenter 1 << 2
|
||||
#define kCGEventFlagMaskXButton1 1 << 3
|
||||
#define kCGEventFlagMaskXButton2 1 << 4
|
||||
|
||||
|
||||
/* Check for access to Apples accessibility API.
|
||||
*/
|
||||
extern bool is_accessibility_enabled();
|
||||
|
||||
/* Converts an OSX key code and event mask to the appropriate Unicode character
|
||||
* representation.
|
||||
*/
|
||||
extern UniCharCount keycode_to_unicode(CGEventRef event_ref, UniChar *buffer, UniCharCount size);
|
||||
|
||||
/* Converts an OSX keycode to the appropriate IOHook scancode constant.
|
||||
*/
|
||||
extern uint16_t keycode_to_scancode(UInt64 keycode);
|
||||
|
||||
/* Converts a IOHook scancode constant to the appropriate OSX keycode.
|
||||
*/
|
||||
extern UInt64 scancode_to_keycode(uint16_t keycode);
|
||||
|
||||
|
||||
/* Initialize items required for KeyCodeToKeySym() and KeySymToUnicode()
|
||||
* functionality. This method is called by OnLibraryLoad() and may need to be
|
||||
* called in combination with UnloadInputHelper() if the native keyboard layout
|
||||
* is changed.
|
||||
*/
|
||||
extern void load_input_helper();
|
||||
|
||||
/* De-initialize items required for KeyCodeToKeySym() and KeySymToUnicode()
|
||||
* functionality. This method is called by OnLibraryUnload() and may need to be
|
||||
* called in combination with LoadInputHelper() if the native keyboard layout
|
||||
* is changed.
|
||||
*/
|
||||
extern void unload_input_helper();
|
||||
|
||||
#endif
|
542
vendor/github.com/robotn/gohook/hook/darwin/input_c.h
generated
vendored
Normal file
542
vendor/github.com/robotn/gohook/hook/darwin/input_c.h
generated
vendored
Normal file
@ -0,0 +1,542 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_COREFOUNDATION
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
#ifndef USE_WEAK_IMPORT
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "input.h"
|
||||
#include "../iohook.h"
|
||||
#include "../logger_c.h"
|
||||
|
||||
// Current dead key state.
|
||||
#if defined(USE_CARBON_LEGACY) || defined(USE_COREFOUNDATION)
|
||||
static UInt32 deadkey_state;
|
||||
#endif
|
||||
|
||||
// Input source data for the keyboard.
|
||||
#if defined(USE_CARBON_LEGACY)
|
||||
static KeyboardLayoutRef prev_keyboard_layout = NULL;
|
||||
#elif defined(USE_COREFOUNDATION)
|
||||
static TISInputSourceRef prev_keyboard_layout = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef USE_WEAK_IMPORT
|
||||
// Required to dynamically check for AXIsProcessTrustedWithOptions availability.
|
||||
extern Boolean AXIsProcessTrustedWithOptions(CFDictionaryRef options) __attribute__((weak_import));
|
||||
extern CFStringRef kAXTrustedCheckOptionPrompt __attribute__((weak_import));
|
||||
#else
|
||||
static Boolean (*AXIsProcessTrustedWithOptions_t)(CFDictionaryRef);
|
||||
#endif
|
||||
|
||||
bool is_accessibility_enabled() {
|
||||
bool is_enabled = false;
|
||||
|
||||
#ifdef USE_WEAK_IMPORT
|
||||
// Check and make sure assistive devices is enabled.
|
||||
if (AXIsProcessTrustedWithOptions != NULL) {
|
||||
// New accessibility API 10.9 and later.
|
||||
const void * keys[] = { kAXTrustedCheckOptionPrompt };
|
||||
const void * values[] = { kCFBooleanTrue };
|
||||
|
||||
CFDictionaryRef options = CFDictionaryCreate(
|
||||
kCFAllocatorDefault,
|
||||
keys,
|
||||
values,
|
||||
sizeof(keys) / sizeof(*keys),
|
||||
&kCFCopyStringDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
is_enabled = AXIsProcessTrustedWithOptions(options);
|
||||
}
|
||||
#else
|
||||
// Dynamically load the application services framework for examination.
|
||||
*(void **) (&AXIsProcessTrustedWithOptions_t) = dlsym(RTLD_DEFAULT, "AXIsProcessTrustedWithOptions");
|
||||
const char *dlError = dlerror();
|
||||
if (AXIsProcessTrustedWithOptions_t != NULL && dlError == NULL) {
|
||||
// Check for property CFStringRef kAXTrustedCheckOptionPrompt
|
||||
void ** kAXTrustedCheckOptionPrompt_t = dlsym(RTLD_DEFAULT, "kAXTrustedCheckOptionPrompt");
|
||||
|
||||
dlError = dlerror();
|
||||
if (kAXTrustedCheckOptionPrompt_t != NULL && dlError == NULL) {
|
||||
// New accessibility API 10.9 and later.
|
||||
const void * keys[] = { *kAXTrustedCheckOptionPrompt_t };
|
||||
const void * values[] = { kCFBooleanTrue };
|
||||
|
||||
CFDictionaryRef options = CFDictionaryCreate(
|
||||
kCFAllocatorDefault,
|
||||
keys,
|
||||
values,
|
||||
sizeof(keys) / sizeof(*keys),
|
||||
&kCFCopyStringDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
is_enabled = (*AXIsProcessTrustedWithOptions_t)(options);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
#ifndef USE_WEAK_IMPORT
|
||||
if (dlError != NULL) {
|
||||
// Could not load the AXIsProcessTrustedWithOptions function!
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: %s.\n",
|
||||
__FUNCTION__, __LINE__, dlError);
|
||||
}
|
||||
#endif
|
||||
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Weak import AXIsProcessTrustedWithOptions not found.\n",
|
||||
__FUNCTION__, __LINE__, dlError);
|
||||
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Falling back to AXAPIEnabled().\n",
|
||||
__FUNCTION__, __LINE__, dlError);
|
||||
|
||||
// Old accessibility check 10.8 and older.
|
||||
is_enabled = AXAPIEnabled();
|
||||
}
|
||||
|
||||
return is_enabled;
|
||||
}
|
||||
|
||||
|
||||
UniCharCount keycode_to_unicode(CGEventRef event_ref, UniChar *buffer, UniCharCount size) {
|
||||
UniCharCount count = 0;
|
||||
|
||||
#if defined(USE_CARBON_LEGACY)
|
||||
KeyboardLayoutRef curr_keyboard_layout;
|
||||
void *inputData = NULL;
|
||||
if (KLGetCurrentKeyboardLayout(&curr_keyboard_layout) == noErr) {
|
||||
if (KLGetKeyboardLayoutProperty(curr_keyboard_layout, kKLuchrData, (const void **) &inputData) != noErr) {
|
||||
inputData = NULL;
|
||||
}
|
||||
}
|
||||
#elif defined(USE_COREFOUNDATION)
|
||||
CFDataRef inputData = NULL;
|
||||
if (CFEqual(CFRunLoopGetCurrent(), CFRunLoopGetMain())) {
|
||||
// NOTE The following block must execute on the main runloop,
|
||||
// Ex: CFEqual(CFRunLoopGetCurrent(), CFRunLoopGetMain()) to avoid
|
||||
// Exception detected while handling key input and TSMProcessRawKeyCode failed
|
||||
// (-192) errors.
|
||||
TISInputSourceRef curr_keyboard_layout = TISCopyCurrentKeyboardLayoutInputSource();
|
||||
if (curr_keyboard_layout != NULL && CFGetTypeID(curr_keyboard_layout) == TISInputSourceGetTypeID()) {
|
||||
CFDataRef data = (CFDataRef) TISGetInputSourceProperty(curr_keyboard_layout, kTISPropertyUnicodeKeyLayoutData);
|
||||
if (data != NULL && CFGetTypeID(data) == CFDataGetTypeID() && CFDataGetLength(data) > 0) {
|
||||
inputData = (CFDataRef) data;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the keyboard layout has changed to see if the dead key state needs to be discarded.
|
||||
if (prev_keyboard_layout != NULL && curr_keyboard_layout != NULL && CFEqual(curr_keyboard_layout, prev_keyboard_layout) == false) {
|
||||
deadkey_state = 0x00;
|
||||
}
|
||||
|
||||
// Release the previous keyboard layout.
|
||||
if (prev_keyboard_layout != NULL) {
|
||||
CFRelease(prev_keyboard_layout);
|
||||
prev_keyboard_layout = NULL;
|
||||
}
|
||||
|
||||
// Set the previous keyboard layout to the current layout.
|
||||
if (curr_keyboard_layout != NULL) {
|
||||
prev_keyboard_layout = curr_keyboard_layout;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_CARBON_LEGACY) || defined(USE_COREFOUNDATION)
|
||||
if (inputData != NULL) {
|
||||
#ifdef USE_CARBON_LEGACY
|
||||
const UCKeyboardLayout *keyboard_layout = (const UCKeyboardLayout *) inputData;
|
||||
#else
|
||||
const UCKeyboardLayout *keyboard_layout = (const UCKeyboardLayout*) CFDataGetBytePtr(inputData);
|
||||
#endif
|
||||
|
||||
if (keyboard_layout != NULL) {
|
||||
//Extract keycode and modifier information.
|
||||
CGKeyCode keycode = CGEventGetIntegerValueField(event_ref, kCGKeyboardEventKeycode);
|
||||
CGEventFlags modifiers = CGEventGetFlags(event_ref);
|
||||
|
||||
// Disable all command modifiers for translation. This is required
|
||||
// so UCKeyTranslate will provide a keysym for the separate event.
|
||||
static const CGEventFlags cmd_modifiers = kCGEventFlagMaskCommand |
|
||||
kCGEventFlagMaskControl | kCGEventFlagMaskAlternate;
|
||||
modifiers &= ~cmd_modifiers;
|
||||
|
||||
// I don't know why but UCKeyTranslate does not process the
|
||||
// kCGEventFlagMaskAlphaShift (A.K.A. Caps Lock Mask) correctly.
|
||||
// We need to basically turn off the mask and process the capital
|
||||
// letters after UCKeyTranslate().
|
||||
bool is_caps_lock = modifiers & kCGEventFlagMaskAlphaShift;
|
||||
modifiers &= ~kCGEventFlagMaskAlphaShift;
|
||||
|
||||
// Run the translation with the saved deadkey_state.
|
||||
OSStatus status = UCKeyTranslate(
|
||||
keyboard_layout,
|
||||
keycode,
|
||||
kUCKeyActionDown, //kUCKeyActionDisplay,
|
||||
(modifiers >> 16) & 0xFF, //(modifiers >> 16) & 0xFF, || (modifiers >> 8) & 0xFF,
|
||||
LMGetKbdType(),
|
||||
kNilOptions, //kNilOptions, //kUCKeyTranslateNoDeadKeysMask
|
||||
&deadkey_state,
|
||||
size,
|
||||
&count,
|
||||
buffer);
|
||||
|
||||
if (status == noErr && count > 0) {
|
||||
if (is_caps_lock) {
|
||||
// We *had* a caps lock mask so we need to convert to uppercase.
|
||||
CFMutableStringRef keytxt = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault, buffer, count, size, kCFAllocatorNull);
|
||||
if (keytxt != NULL) {
|
||||
CFLocaleRef locale = CFLocaleCopyCurrent();
|
||||
CFStringUppercase(keytxt, locale);
|
||||
CFRelease(locale);
|
||||
CFRelease(keytxt);
|
||||
}
|
||||
else {
|
||||
// There was an problem creating the CFMutableStringRef.
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Make sure the buffer count is zero if an error occurred.
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
CGEventKeyboardGetUnicodeString(event_ref, size, &count, buffer);
|
||||
#endif
|
||||
|
||||
// The following codes should not be processed because they are invalid.
|
||||
if (count == 1) {
|
||||
switch (buffer[0]) {
|
||||
case 0x01: // Home
|
||||
case 0x04: // End
|
||||
case 0x05: // Help Key
|
||||
case 0x10: // Function Keys
|
||||
case 0x0B: // Page Up
|
||||
case 0x0C: // Page Down
|
||||
case 0x1F: // Volume Up
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static const uint16_t keycode_scancode_table[][2] = {
|
||||
/* idx { keycode, scancode }, */
|
||||
/* 0 */ { VC_A, kVK_Undefined }, // 0x00
|
||||
/* 1 */ { VC_S, kVK_Escape }, // 0x01
|
||||
/* 2 */ { VC_D, kVK_ANSI_1 }, // 0x02
|
||||
/* 3 */ { VC_F, kVK_ANSI_2 }, // 0x03
|
||||
/* 4 */ { VC_H, kVK_ANSI_3 }, // 0x04
|
||||
/* 5 */ { VC_G, kVK_ANSI_4 }, // 0x05
|
||||
/* 6 */ { VC_Z, kVK_ANSI_5 }, // 0x07
|
||||
/* 7 */ { VC_X, kVK_ANSI_6 }, // 0x08
|
||||
/* 8 */ { VC_C, kVK_ANSI_7 }, // 0x09
|
||||
/* 9 */ { VC_V, kVK_ANSI_8 }, // 0x0A
|
||||
/* 10 */ { VC_UNDEFINED, kVK_ANSI_9 }, // 0x0B
|
||||
/* 11 */ { VC_B, kVK_ANSI_0 }, // 0x0C
|
||||
/* 12 */ { VC_Q, kVK_ANSI_Minus }, // 0x0D
|
||||
/* 13 */ { VC_W, kVK_ANSI_Equal }, // 0x0E
|
||||
/* 14 */ { VC_E, kVK_Delete }, // 0x0F
|
||||
/* 15 */ { VC_R, kVK_Tab }, // 0x10
|
||||
/* 16 */ { VC_Y, kVK_ANSI_Q }, // 0x11
|
||||
/* 17 */ { VC_T, kVK_ANSI_W }, // 0x12
|
||||
/* 18 */ { VC_1, kVK_ANSI_E }, // 0x13
|
||||
/* 19 */ { VC_2, kVK_ANSI_R }, // 0x14
|
||||
/* 20 */ { VC_3, kVK_ANSI_T }, // 0x15
|
||||
/* 21 */ { VC_4, kVK_ANSI_Y }, // 0x16
|
||||
/* 22 */ { VC_6, kVK_ANSI_U }, // 0x17
|
||||
/* 23 */ { VC_5, kVK_ANSI_I }, // 0x18
|
||||
/* 24 */ { VC_EQUALS, kVK_ANSI_O }, // 0x19
|
||||
/* 25 */ { VC_9, kVK_ANSI_P }, // 0x19
|
||||
/* 26 */ { VC_7, kVK_ANSI_LeftBracket }, // 0x1A
|
||||
/* 27 */ { VC_MINUS, kVK_ANSI_RightBracket }, // 0x1B
|
||||
/* 28 */ { VC_8, kVK_Return }, // 0x1C
|
||||
/* 29 */ { VC_0, kVK_Control }, // 0x1D
|
||||
/* 30 */ { VC_CLOSE_BRACKET, kVK_ANSI_A }, // 0x1E
|
||||
/* 31 */ { VC_O, kVK_ANSI_S }, // 0x1F
|
||||
/* 32 */ { VC_U, kVK_ANSI_D }, // 0x20
|
||||
/* 33 */ { VC_OPEN_BRACKET, kVK_ANSI_F }, // 0x21
|
||||
/* 34 */ { VC_I, kVK_ANSI_G }, // 0x22
|
||||
/* 35 */ { VC_P, kVK_ANSI_H }, // 0x23
|
||||
/* 36 */ { VC_ENTER, kVK_ANSI_J }, // 0x24
|
||||
/* 37 */ { VC_L, kVK_ANSI_K }, // 0x25
|
||||
/* 38 */ { VC_J, kVK_ANSI_L }, // 0x26
|
||||
/* 39 */ { VC_QUOTE, kVK_ANSI_Semicolon }, // 0x27
|
||||
/* 40 */ { VC_K, kVK_ANSI_Quote }, // 0x28
|
||||
/* 41 */ { VC_SEMICOLON, kVK_ANSI_Grave }, // 0x29
|
||||
/* 42 */ { VC_BACK_SLASH, kVK_Shift }, // 0x2A
|
||||
/* 43 */ { VC_COMMA, kVK_ANSI_Backslash }, // 0x2B
|
||||
/* 44 */ { VC_SLASH, kVK_ANSI_Z }, // 0x2C
|
||||
/* 45 */ { VC_N, kVK_ANSI_X }, // 0x2D
|
||||
/* 46 */ { VC_M, kVK_ANSI_C }, // 0x2E
|
||||
/* 47 */ { VC_PERIOD, kVK_ANSI_V }, // 0x2F
|
||||
/* 48 */ { VC_TAB, kVK_ANSI_B }, // 0x30
|
||||
/* 49 */ { VC_SPACE, kVK_ANSI_N }, // 0x31
|
||||
/* 50 */ { VC_BACKQUOTE, kVK_ANSI_M }, // 0x32
|
||||
/* 51 */ { VC_BACKSPACE, kVK_ANSI_Comma }, // 0x33
|
||||
/* 52 */ { VC_UNDEFINED, kVK_ANSI_Period }, // 0x34
|
||||
/* 53 */ { VC_ESCAPE, kVK_ANSI_Slash }, // 0x35
|
||||
/* 54 */ { VC_META_R, kVK_RightShift }, // 0x36
|
||||
/* 55 */ { VC_META_L, kVK_ANSI_KeypadMultiply }, // 0x37
|
||||
/* 56 */ { VC_SHIFT_L, kVK_Option }, // 0x38
|
||||
/* 57 */ { VC_CAPS_LOCK, kVK_Space }, // 0x39
|
||||
/* 58 */ { VC_ALT_L, kVK_CapsLock }, // 0x3A
|
||||
/* 59 */ { VC_CONTROL_L, kVK_F1 }, // 0x3B
|
||||
/* 60 */ { VC_SHIFT_R, kVK_F2 }, // 0x3C
|
||||
/* 61 */ { VC_ALT_R, kVK_F3 }, // 0x3D
|
||||
/* 62 */ { VC_CONTROL_R, kVK_F4 }, // 0x3E
|
||||
/* 63 */ { VC_UNDEFINED, kVK_F5 }, // 0x3F
|
||||
/* 64 */ { VC_F17, kVK_F6 }, // 0x40
|
||||
/* 65 */ { VC_KP_SEPARATOR, kVK_F7 }, // 0x41
|
||||
/* 66 */ { VC_UNDEFINED, kVK_F8 }, // 0x42
|
||||
/* 67 */ { VC_KP_MULTIPLY, kVK_F9 }, // 0x43
|
||||
/* 68 */ { VC_UNDEFINED, kVK_F10 }, // 0x44
|
||||
/* 69 */ { VC_KP_ADD, kVK_ANSI_KeypadClear }, // 0x45
|
||||
/* 70 */ { VC_UNDEFINED, kVK_Undefined }, // 0x46
|
||||
/* 71 */ { VC_NUM_LOCK, kVK_ANSI_Keypad7 }, // 0x47
|
||||
/* 72 */ { VC_VOLUME_UP, kVK_ANSI_Keypad8 }, // 0x48
|
||||
/* 73 */ { VC_VOLUME_DOWN, kVK_ANSI_Keypad9 }, // 0x49
|
||||
/* 74 */ { VC_VOLUME_MUTE, kVK_ANSI_KeypadMinus }, // 0x4A
|
||||
/* 75 */ { VC_KP_DIVIDE, kVK_ANSI_Keypad4 }, // 0x4B
|
||||
/* 76 */ { VC_KP_ENTER, kVK_ANSI_Keypad5 }, // 0x4C
|
||||
/* 77 */ { VC_UNDEFINED, kVK_ANSI_Keypad6 }, // 0x4D
|
||||
/* 78 */ { VC_KP_SUBTRACT, kVK_ANSI_KeypadPlus }, // 0x4E
|
||||
/* 79 */ { VC_F18, kVK_ANSI_Keypad1 }, // 0x4F
|
||||
/* 80 */ { VC_F19, kVK_ANSI_Keypad2 }, // 0x50
|
||||
/* 81 */ { VC_KP_EQUALS, kVK_ANSI_Keypad3 }, // 0x51
|
||||
/* 82 */ { VC_KP_0, kVK_ANSI_Keypad0 }, // 0x52
|
||||
/* 83 */ { VC_KP_1, kVK_ANSI_KeypadDecimal }, // 0x53
|
||||
/* 84 */ { VC_KP_2, kVK_Undefined }, // 0x54
|
||||
/* 85 */ { VC_KP_3, kVK_Undefined }, // 0x55
|
||||
/* 86 */ { VC_KP_4, kVK_Undefined }, // 0x56
|
||||
/* 87 */ { VC_KP_5, kVK_F11 }, // 0x57
|
||||
/* 88 */ { VC_KP_6, kVK_F12 }, // 0x58
|
||||
/* 89 */ { VC_KP_7, kVK_Undefined }, // 0x59
|
||||
/* 90 */ { VC_F20, kVK_Undefined }, // 0x5A
|
||||
/* 91 */ { VC_KP_8, kVK_F13 }, // 0x5B
|
||||
/* 92 */ { VC_KP_9, kVK_F14 }, // 0x5C
|
||||
/* 93 */ { VC_YEN, kVK_F15 }, // 0x5D
|
||||
/* 94 */ { VC_UNDERSCORE, kVK_Undefined }, // 0x5E
|
||||
/* 95 */ { VC_KP_COMMA, kVK_Undefined }, // 0x5F
|
||||
/* 96 */ { VC_F5, kVK_Undefined }, // 0x60
|
||||
/* 97 */ { VC_F6, kVK_Undefined }, // 0x61
|
||||
/* 98 */ { VC_F7, kVK_Undefined }, // 0x62
|
||||
/* 99 */ { VC_F3, kVK_F16 }, // 0x63
|
||||
/* 100 */ { VC_F8, kVK_F17 }, // 0x64
|
||||
/* 101 */ { VC_F9, kVK_F18 }, // 0x65
|
||||
/* 102 */ { VC_UNDEFINED, kVK_F19 }, // 0x66
|
||||
/* 103 */ { VC_F11, kVK_F20 }, // 0x67
|
||||
/* 104 */ { VC_KATAKANA, kVK_Undefined }, // 0x68
|
||||
/* 105 */ { VC_F13, kVK_Undefined }, // 0x69
|
||||
/* 106 */ { VC_F16, kVK_Undefined }, // 0x6A
|
||||
/* 107 */ { VC_F14, kVK_Undefined }, // 0x6B
|
||||
/* 108 */ { VC_UNDEFINED, kVK_Undefined }, // 0x6C FIXME kVK_JIS_Eisu same as Caps Lock ?
|
||||
/* 109 */ { VC_F10, kVK_Undefined }, // 0x6D
|
||||
/* 110 */ { VC_UNDEFINED, kVK_Undefined }, // 0x6E
|
||||
/* 111 */ { VC_F12, kVK_Undefined }, // 0x6F
|
||||
/* 112 */ { VC_UNDEFINED, kVK_JIS_Kana }, // 0x70
|
||||
/* 113 */ { VC_F15, kVK_Undefined }, // 0x71
|
||||
/* 114 */ { VC_INSERT, kVK_Undefined }, // 0x72
|
||||
/* 115 */ { VC_HOME, kVK_JIS_Underscore }, // 0x73
|
||||
/* 116 */ { VC_PAGE_UP, kVK_Undefined }, // 0x74
|
||||
/* 117 */ { VC_DELETE, kVK_Undefined }, // 0x75
|
||||
/* 118 */ { VC_F4, kVK_Undefined }, // 0x76
|
||||
/* 119 */ { VC_END, kVK_Undefined }, // 0x77
|
||||
/* 120 */ { VC_F2, kVK_Undefined }, // 0x78
|
||||
/* 121 */ { VC_PAGE_DOWN, kVK_Undefined }, // 0x79
|
||||
/* 122 */ { VC_F1, kVK_Undefined }, // 0x7A
|
||||
/* 123 */ { VC_LEFT, kVK_Undefined }, // 0x7B
|
||||
/* 124 */ { VC_RIGHT, kVK_Undefined }, // 0x7C
|
||||
/* 125 */ { VC_DOWN, kVK_JIS_Yen }, // 0x7D
|
||||
/* 126 */ { VC_UP, kVK_JIS_KeypadComma }, // 0x7E
|
||||
/* 127 */ { VC_UNDEFINED, kVK_Undefined }, // 0x7F
|
||||
|
||||
// No Offset Offset (i & 0x007F) + 128
|
||||
|
||||
/* 128 */ { VC_UNDEFINED, kVK_Undefined }, // 0x80
|
||||
/* 129 */ { VC_UNDEFINED, kVK_Undefined }, // 0x81
|
||||
/* 130 */ { VC_UNDEFINED, kVK_Undefined }, // 0x82
|
||||
/* 131 */ { VC_UNDEFINED, kVK_Undefined }, // 0x83
|
||||
/* 132 */ { VC_UNDEFINED, kVK_Undefined }, // 0x84
|
||||
/* 133 */ { VC_UNDEFINED, kVK_Undefined }, // 0x85
|
||||
/* 134 */ { VC_UNDEFINED, kVK_Undefined }, // 0x86
|
||||
/* 135 */ { VC_UNDEFINED, kVK_Undefined }, // 0x87
|
||||
/* 136 */ { VC_UNDEFINED, kVK_Undefined }, // 0x88
|
||||
/* 137 */ { VC_UNDEFINED, kVK_Undefined }, // 0x89
|
||||
/* 138 */ { VC_UNDEFINED, kVK_Undefined }, // 0x8A
|
||||
/* 139 */ { VC_UNDEFINED, kVK_Undefined }, // 0x8B
|
||||
/* 140 */ { VC_UNDEFINED, kVK_Undefined }, // 0x8C
|
||||
/* 141 */ { VC_UNDEFINED, kVK_ANSI_KeypadEquals }, // 0x8D
|
||||
/* 142 */ { VC_UNDEFINED, kVK_Undefined }, // 0x8E
|
||||
/* 143 */ { VC_UNDEFINED, kVK_Undefined }, // 0x8F
|
||||
/* 144 */ { VC_UNDEFINED, kVK_MEDIA_Previous }, // 0x90
|
||||
/* 145 */ { VC_UNDEFINED, kVK_Undefined }, // 0x91
|
||||
/* 146 */ { VC_UNDEFINED, kVK_Undefined }, // 0x92
|
||||
/* 147 */ { VC_UNDEFINED, kVK_Undefined }, // 0x93
|
||||
/* 148 */ { VC_UNDEFINED, kVK_Undefined }, // 0x94
|
||||
/* 149 */ { VC_UNDEFINED, kVK_Undefined }, // 0x95
|
||||
/* 150 */ { VC_UNDEFINED, kVK_Undefined }, // 0x96
|
||||
/* 151 */ { VC_UNDEFINED, kVK_Undefined }, // 0x97
|
||||
/* 152 */ { VC_UNDEFINED, kVK_Undefined }, // 0x98
|
||||
/* 153 */ { VC_UNDEFINED, kVK_MEDIA_Next }, // 0x99
|
||||
/* 154 */ { VC_UNDEFINED, kVK_Undefined }, // 0x9A
|
||||
/* 155 */ { VC_UNDEFINED, kVK_Undefined }, // 0x9B
|
||||
/* 156 */ { VC_UNDEFINED, kVK_ANSI_KeypadEnter }, // 0x9C
|
||||
/* 157 */ { VC_UNDEFINED, kVK_RightControl }, // 0x9D
|
||||
/* 158 */ { VC_UNDEFINED, kVK_Undefined }, // 0x9E
|
||||
/* 159 */ { VC_UNDEFINED, kVK_Undefined }, // 0x9F
|
||||
/* 160 */ { VC_UNDEFINED, kVK_Mute }, // 0xA0
|
||||
/* 161 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA1
|
||||
/* 162 */ { VC_UNDEFINED, kVK_MEDIA_Play }, // 0xA2
|
||||
/* 163 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA3
|
||||
/* 164 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA4
|
||||
/* 165 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA5
|
||||
/* 166 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA6
|
||||
/* 167 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA7
|
||||
/* 168 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA8
|
||||
/* 169 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA9
|
||||
/* 170 */ { VC_UNDEFINED, kVK_Undefined }, // 0xAA
|
||||
/* 171 */ { VC_UNDEFINED, kVK_Undefined }, // 0xAB
|
||||
/* 172 */ { VC_UNDEFINED, kVK_NX_Eject }, // 0xAC
|
||||
/* 173 */ { VC_UNDEFINED, kVK_Undefined }, // 0xAD
|
||||
/* 174 */ { VC_UNDEFINED, kVK_VolumeDown }, // 0xAE
|
||||
/* 175 */ { VC_UNDEFINED, kVK_Undefined }, // 0xAF
|
||||
/* 176 */ { VC_UNDEFINED, kVK_VolumeUp }, // 0xB0
|
||||
/* 177 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB1
|
||||
/* 178 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB2
|
||||
/* 179 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB3
|
||||
/* 180 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB4
|
||||
/* 181 */ { VC_UNDEFINED, kVK_ANSI_KeypadDivide }, // 0xB5
|
||||
/* 182 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB6
|
||||
/* 183 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB7
|
||||
/* 184 */ { VC_UNDEFINED, kVK_RightOption }, // 0xB8
|
||||
/* 185 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB9
|
||||
/* 186 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBA
|
||||
/* 187 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBB
|
||||
/* 188 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBC
|
||||
/* 189 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBD
|
||||
/* 190 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBE
|
||||
/* 191 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBF
|
||||
/* 192 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC0
|
||||
/* 193 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC1
|
||||
/* 194 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC2
|
||||
/* 195 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC3
|
||||
/* 196 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC4
|
||||
/* 197 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC5
|
||||
/* 198 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC6
|
||||
/* 199 */ { VC_UNDEFINED, kVK_Home }, // 0xC7
|
||||
/* 200 */ { VC_UNDEFINED, kVK_UpArrow }, // 0xC8
|
||||
/* 201 */ { VC_UNDEFINED, kVK_PageUp }, // 0xC9
|
||||
/* 202 */ { VC_UNDEFINED, kVK_Undefined }, // 0xCA
|
||||
/* 203 */ { VC_UNDEFINED, kVK_LeftArrow }, // 0xCB
|
||||
/* 204 */ { VC_UNDEFINED, kVK_Undefined }, // 0xCC
|
||||
/* 205 */ { VC_UNDEFINED, kVK_RightArrow }, // 0xCD
|
||||
/* 206 */ { VC_UNDEFINED, kVK_Undefined }, // 0xCE
|
||||
/* 207 */ { VC_UNDEFINED, kVK_End }, // 0xCF
|
||||
/* 208 */ { VC_UNDEFINED, kVK_DownArrow }, // 0xD0
|
||||
/* 209 */ { VC_UNDEFINED, kVK_PageDown }, // 0xD1
|
||||
/* 210 */ { VC_UNDEFINED, kVK_Help }, // 0xD2
|
||||
/* 211 */ { VC_UNDEFINED, kVK_ForwardDelete }, // 0xD3
|
||||
/* 212 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD4
|
||||
/* 213 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD5
|
||||
/* 214 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD6
|
||||
/* 215 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD7
|
||||
/* 216 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD8
|
||||
/* 217 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD9
|
||||
/* 218 */ { VC_UNDEFINED, kVK_Undefined }, // 0xDA
|
||||
/* 219 */ { VC_UNDEFINED, kVK_Command }, // 0xDB
|
||||
/* 220 */ { VC_UNDEFINED, kVK_RightCommand }, // 0xDC
|
||||
/* 221 */ { VC_UNDEFINED, kVK_Undefined }, // 0xDD
|
||||
/* 222 */ { VC_UNDEFINED, kVK_NX_Power }, // 0xDE
|
||||
/* 223 */ { VC_UNDEFINED, kVK_Undefined }, // 0xDF
|
||||
/* 224 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE0
|
||||
/* 225 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE1
|
||||
/* 226 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE2
|
||||
/* 227 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE3
|
||||
/* 228 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE4
|
||||
/* 229 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE5
|
||||
/* 230 */ { VC_POWER, kVK_Undefined }, // 0xE6
|
||||
/* 231 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE7
|
||||
/* 232 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE8
|
||||
/* 233 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE9
|
||||
/* 234 */ { VC_UNDEFINED, kVK_Undefined }, // 0xEA
|
||||
/* 235 */ { VC_UNDEFINED, kVK_Undefined }, // 0xEB
|
||||
/* 236 */ { VC_UNDEFINED, kVK_Undefined }, // 0xEC
|
||||
/* 237 */ { VC_UNDEFINED, kVK_Undefined }, // 0xED
|
||||
/* 238 */ { VC_MEDIA_EJECT, kVK_Undefined }, // 0xEE
|
||||
/* 239 */ { VC_UNDEFINED, kVK_Undefined }, // 0xEF
|
||||
/* 240 */ { VC_MEDIA_PLAY, kVK_Undefined }, // 0xF0
|
||||
/* 241 */ { VC_MEDIA_NEXT, kVK_Undefined }, // 0xF1
|
||||
/* 242 */ { VC_MEDIA_PREVIOUS, kVK_Undefined }, // 0xF2
|
||||
/* 243 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF3
|
||||
/* 244 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF4
|
||||
/* 245 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF5
|
||||
/* 246 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF6
|
||||
/* 247 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF7
|
||||
/* 248 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF8
|
||||
/* 249 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF9
|
||||
/* 250 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFA
|
||||
/* 251 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFB
|
||||
/* 252 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFC
|
||||
/* 253 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFD
|
||||
/* 254 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFE
|
||||
/* 255 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFF
|
||||
};
|
||||
|
||||
uint16_t keycode_to_scancode(UInt64 keycode) {
|
||||
uint16_t scancode = VC_UNDEFINED;
|
||||
|
||||
// Bound check 0 <= keycode < 256
|
||||
if (keycode < sizeof(keycode_scancode_table) / sizeof(keycode_scancode_table[0])) {
|
||||
scancode = keycode_scancode_table[keycode][0];
|
||||
}
|
||||
|
||||
return scancode;
|
||||
}
|
||||
|
||||
UInt64 scancode_to_keycode(uint16_t scancode) {
|
||||
UInt64 keycode = kVK_Undefined;
|
||||
|
||||
// Bound check 0 <= keycode < 128
|
||||
if (scancode < 128) {
|
||||
keycode = keycode_scancode_table[scancode][1];
|
||||
}
|
||||
else {
|
||||
// Calculate the upper offset.
|
||||
unsigned short i = (scancode & 0x007F) | 0x80;
|
||||
|
||||
if (i < sizeof(keycode_scancode_table) / sizeof(keycode_scancode_table[1])) {
|
||||
keycode = keycode_scancode_table[i][1];
|
||||
}
|
||||
}
|
||||
|
||||
return keycode;
|
||||
}
|
||||
|
||||
void load_input_helper() {
|
||||
#if defined(USE_CARBON_LEGACY) || defined(USE_COREFOUNDATION)
|
||||
// Start with a fresh dead key state.
|
||||
//curr_deadkey_state = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void unload_input_helper() {
|
||||
#if defined(USE_CARBON_LEGACY) || defined(USE_COREFOUNDATION)
|
||||
if (prev_keyboard_layout != NULL) {
|
||||
// Cleanup tracking of the previous layout.
|
||||
CFRelease(prev_keyboard_layout);
|
||||
prev_keyboard_layout = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
522
vendor/github.com/robotn/gohook/hook/darwin/properties_c.h
generated
vendored
Normal file
522
vendor/github.com/robotn/gohook/hook/darwin/properties_c.h
generated
vendored
Normal file
@ -0,0 +1,522 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_CARBON_LEGACY
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
#ifdef USE_COREFOUNDATION
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
#ifdef USE_IOKIT
|
||||
#include <IOKit/hidsystem/IOHIDLib.h>
|
||||
#include <IOKit/hidsystem/IOHIDParameter.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "../iohook.h"
|
||||
#include "input.h"
|
||||
// #include "../logger_c.h"
|
||||
|
||||
IOHOOK_API screen_data* hook_create_screen_info(unsigned char *count) {
|
||||
CGError status = kCGErrorFailure;
|
||||
screen_data* screens = NULL;
|
||||
|
||||
// Initialize count to zero.
|
||||
*count = 0;
|
||||
|
||||
// Allocate memory to hold each display id. We will just allocate our MAX
|
||||
// because its only about 1K of memory.
|
||||
// TODO This can probably be realistically cut to something like 16 or 32....
|
||||
// If you have more than 32 monitors, send me a picture and make a donation ;)
|
||||
CGDirectDisplayID *display_ids = malloc(sizeof(CGDirectDisplayID) * UCHAR_MAX);
|
||||
if (display_ids != NULL) {
|
||||
// NOTE Pass UCHAR_MAX to make sure uint32_t doesn't overflow uint8_t.
|
||||
// TOOD Test/Check whether CGGetOnlineDisplayList is more suitable...
|
||||
status = CGGetActiveDisplayList(UCHAR_MAX, display_ids, (uint32_t *) count);
|
||||
|
||||
// If there is no error and at least one monitor.
|
||||
if (status == kCGErrorSuccess && *count > 0) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: CGGetActiveDisplayList: %li.\n",
|
||||
__FUNCTION__, __LINE__, *count);
|
||||
|
||||
// Allocate memory for the number of screens found.
|
||||
screens = malloc(sizeof(screen_data) * (*count));
|
||||
if (screens != NULL) {
|
||||
uint8_t i;
|
||||
for (i = 0; i < *count; i++) {
|
||||
//size_t width = CGDisplayPixelsWide(display_ids[i]);
|
||||
//size_t height = CGDisplayPixelsHigh(display_ids[i]);
|
||||
CGRect boundsDisp = CGDisplayBounds(display_ids[i]);
|
||||
if (boundsDisp.size.width > 0 && boundsDisp.size.height > 0) {
|
||||
screens[i] = (screen_data) {
|
||||
.number = i + 1,
|
||||
//TODO: make sure we follow the same convention for the origin
|
||||
//in all other platform implementations (upper-left)
|
||||
//TODO: document the approach with examples in order to show different
|
||||
//cases -> different resolutions (secondary monitors origin might be
|
||||
//negative)
|
||||
.x = boundsDisp.origin.x,
|
||||
.y = boundsDisp.origin.y,
|
||||
.width = boundsDisp.size.width,
|
||||
.height = boundsDisp.size.height
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: multiple_get_screen_info failed: %ld. Fallback.\n",
|
||||
__FUNCTION__, __LINE__, status);
|
||||
|
||||
size_t width = CGDisplayPixelsWide(CGMainDisplayID());
|
||||
size_t height = CGDisplayPixelsHigh(CGMainDisplayID());
|
||||
|
||||
if (width > 0 && height > 0) {
|
||||
screens = malloc(sizeof(screen_data));
|
||||
|
||||
if (screens != NULL) {
|
||||
*count = 1;
|
||||
screens[0] = (screen_data) {
|
||||
.number = 1,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = width,
|
||||
.height = height
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Free the id's after we are done.
|
||||
free(display_ids);
|
||||
}
|
||||
|
||||
return screens;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apple's documentation is not very good. I was finally able to find this
|
||||
* information after many hours of googling. Value is the slider value in the
|
||||
* system preferences. That value * 15 is the rate in MS. 66 / the value is the
|
||||
* chars per second rate.
|
||||
*
|
||||
* Value MS Char/Sec
|
||||
*
|
||||
* 1 15 66 * Out of standard range *
|
||||
*
|
||||
* 2 30 33
|
||||
* 6 90 11
|
||||
* 12 180 5.5
|
||||
* 30 450 2.2
|
||||
* 60 900 1.1
|
||||
* 90 1350 0.73
|
||||
* 120 1800 0.55
|
||||
*
|
||||
* V = MS / 15
|
||||
* V = 66 / CharSec
|
||||
*
|
||||
* MS = V * 15
|
||||
* MS = (66 / CharSec) * 15
|
||||
*
|
||||
* CharSec = 66 / V
|
||||
* CharSec = 66 / (MS / 15)
|
||||
*/
|
||||
|
||||
IOHOOK_API long int hook_get_auto_repeat_rate() {
|
||||
#if defined USE_IOKIT || defined USE_COREFOUNDATION || defined USE_CARBON_LEGACY
|
||||
bool successful = false;
|
||||
SInt64 rate;
|
||||
#endif
|
||||
|
||||
long int value = -1;
|
||||
|
||||
#ifdef USE_IOKIT
|
||||
if (!successful) {
|
||||
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
|
||||
if (service) {
|
||||
kern_return_t kren_ret = kIOReturnError;
|
||||
io_connect_t connection;
|
||||
|
||||
kren_ret = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &connection);
|
||||
if (kren_ret == kIOReturnSuccess) {
|
||||
IOByteCount size = sizeof(rate);
|
||||
|
||||
kren_ret = IOHIDGetParameter(connection, CFSTR(kIOHIDKeyRepeatKey), (IOByteCount) sizeof(rate), &rate, &size);
|
||||
if (kren_ret == kIOReturnSuccess) {
|
||||
/* This is in some undefined unit of time that if we happen
|
||||
* to multiply by 900 gives us the time in milliseconds. We
|
||||
* add 0.5 to the result so that when we cast to long we
|
||||
* actually get a rounded result. Saves the math.h depend.
|
||||
*
|
||||
* 33,333,333.0 / 1000.0 / 1000.0 / 1000.0 == 0.033333333 * Fast *
|
||||
* 100,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 0.1
|
||||
* 200,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 0.2
|
||||
* 500,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 0.5
|
||||
* 1,000,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 1
|
||||
* 1,500,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 1.5
|
||||
* 2,000,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 2 * Slow *
|
||||
*/
|
||||
value = (long) (900.0 * ((double) rate) / 1000.0 / 1000.0 / 1000.0 + 0.5);
|
||||
successful = true;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: IOHIDGetParameter: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_COREFOUNDATION
|
||||
if (!successful) {
|
||||
CFTypeRef pref_val = CFPreferencesCopyValue(CFSTR("KeyRepeat"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
|
||||
if (pref_val != NULL && CFGetTypeID(pref_val) == CFNumberGetTypeID()) {
|
||||
if (CFNumberGetValue((CFNumberRef) pref_val, kCFNumberSInt32Type, &rate)) {
|
||||
// This is the slider value, we must multiply by 15 to convert to milliseconds.
|
||||
value = (long) rate * 15;
|
||||
successful = true;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: CFPreferencesCopyValue: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_CARBON_LEGACY
|
||||
if (!successful) {
|
||||
// Apple documentation states that value is in 'ticks'. I am not sure
|
||||
// what that means, but it looks a lot like the arbitrary slider value.
|
||||
rate = LMGetKeyRepThresh();
|
||||
if (rate > -1) {
|
||||
/* This is the slider value, we must multiply by 15 to convert to
|
||||
* milliseconds.
|
||||
*/
|
||||
value = (long) rate * 15;
|
||||
successful = true;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: LMGetKeyRepThresh: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_auto_repeat_delay() {
|
||||
#if defined USE_IOKIT || defined USE_COREFOUNDATION || defined USE_CARBON_LEGACY
|
||||
bool successful = false;
|
||||
SInt64 delay;
|
||||
#endif
|
||||
|
||||
long int value = -1;
|
||||
|
||||
#ifdef USE_IOKIT
|
||||
if (!successful) {
|
||||
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
|
||||
if (service) {
|
||||
kern_return_t kren_ret = kIOReturnError;
|
||||
io_connect_t connection;
|
||||
|
||||
kren_ret = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &connection);
|
||||
if (kren_ret == kIOReturnSuccess) {
|
||||
IOByteCount size = sizeof(delay);
|
||||
|
||||
kren_ret = IOHIDGetParameter(connection, CFSTR(kIOHIDInitialKeyRepeatKey), (IOByteCount) sizeof(delay), &delay, &size);
|
||||
if (kren_ret == kIOReturnSuccess) {
|
||||
/* This is in some undefined unit of time that if we happen
|
||||
* to multiply by 900 gives us the time in milliseconds. We
|
||||
* add 0.5 to the result so that when we cast to long we
|
||||
* actually get a rounded result. Saves the math.h depend.
|
||||
*
|
||||
* 33,333,333.0 / 1000.0 / 1000.0 / 1000.0 == 0.033333333 * Fast *
|
||||
* 100,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 0.1
|
||||
* 200,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 0.2
|
||||
* 500,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 0.5
|
||||
* 1,000,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 1
|
||||
* 1,500,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 1.5
|
||||
* 2,000,000,000.0 / 1000.0 / 1000.0 / 1000.0 == 2 * Slow *
|
||||
*/
|
||||
value = (long) (900.0 * ((double) delay) / 1000.0 / 1000.0 / 1000.0 + 0.5);
|
||||
successful = true;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: IOHIDGetParameter: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_COREFOUNDATION
|
||||
if (!successful) {
|
||||
CFTypeRef pref_val = CFPreferencesCopyValue(CFSTR("InitialKeyRepeat"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
|
||||
if (pref_val != NULL && CFGetTypeID(pref_val) == CFNumberGetTypeID()) {
|
||||
if (CFNumberGetValue((CFNumberRef) pref_val, kCFNumberSInt32Type, &delay)) {
|
||||
// This is the slider value, we must multiply by 15 to convert to
|
||||
// milliseconds.
|
||||
value = (long) delay * 15;
|
||||
successful = true;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: CFPreferencesCopyValue: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_CARBON_LEGACY
|
||||
if (!successful) {
|
||||
// Apple documentation states that value is in 'ticks'. I am not sure
|
||||
// what that means, but it looks a lot like the arbitrary slider value.
|
||||
delay = LMGetKeyThresh();
|
||||
if (delay > -1) {
|
||||
// This is the slider value, we must multiply by 15 to convert to
|
||||
// milliseconds.
|
||||
value = (long) delay * 15;
|
||||
successful = true;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: LMGetKeyThresh: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_pointer_acceleration_multiplier() {
|
||||
#if defined USE_IOKIT || defined USE_COREFOUNDATION
|
||||
bool successful = false;
|
||||
double multiplier;
|
||||
#endif
|
||||
|
||||
long int value = -1;
|
||||
|
||||
#ifdef USE_IOKIT
|
||||
if (!successful) {
|
||||
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
|
||||
|
||||
if (service) {
|
||||
kern_return_t kren_ret = kIOReturnError;
|
||||
io_connect_t connection;
|
||||
|
||||
kren_ret = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &connection);
|
||||
if (kren_ret == kIOReturnSuccess) {
|
||||
// IOByteCount size = sizeof(multiplier);
|
||||
|
||||
kren_ret = IOHIDGetAccelerationWithKey(connection, CFSTR(kIOHIDMouseAccelerationType), &multiplier);
|
||||
if (kren_ret == kIOReturnSuccess) {
|
||||
// Calculate the greatest common factor.
|
||||
|
||||
unsigned long denominator = 1000000, d = denominator;
|
||||
unsigned long numerator = multiplier * denominator, gcf = numerator;
|
||||
|
||||
while (d != 0) {
|
||||
unsigned long i = gcf % d;
|
||||
gcf = d;
|
||||
d = i;
|
||||
}
|
||||
|
||||
value = denominator / gcf;
|
||||
successful = true;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: IOHIDGetAccelerationWithKey: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_COREFOUNDATION
|
||||
if (!successful) {
|
||||
CFTypeRef pref_val = CFPreferencesCopyValue(CFSTR("com.apple.mouse.scaling"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
|
||||
if (pref_val != NULL && CFGetTypeID(pref_val) == CFNumberGetTypeID()) {
|
||||
if (CFNumberGetValue((CFNumberRef) pref_val, kCFNumberSInt32Type, &multiplier)) {
|
||||
value = (long) multiplier;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: CFPreferencesCopyValue: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_pointer_acceleration_threshold() {
|
||||
#if defined USE_COREFOUNDATION
|
||||
bool successful = false;
|
||||
SInt32 threshold;
|
||||
#endif
|
||||
|
||||
long int value = -1;
|
||||
|
||||
#ifdef USE_COREFOUNDATION
|
||||
if (!successful) {
|
||||
CFTypeRef pref_val = CFPreferencesCopyValue(CFSTR("mouseDriverMaxSpeed"), CFSTR("com.apple.universalaccess"), kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
|
||||
if (pref_val != NULL && CFGetTypeID(pref_val) == CFNumberGetTypeID()) {
|
||||
if (CFNumberGetValue((CFNumberRef) pref_val, kCFNumberSInt32Type, &threshold)) {
|
||||
value = (long) threshold;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: CFPreferencesCopyValue: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_pointer_sensitivity() {
|
||||
#ifdef USE_IOKIT
|
||||
bool successful = false;
|
||||
double sensitivity;
|
||||
#endif
|
||||
|
||||
long int value = -1;
|
||||
|
||||
#ifdef USE_IOKIT
|
||||
if (!successful) {
|
||||
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
|
||||
|
||||
if (service) {
|
||||
kern_return_t kren_ret = kIOReturnError;
|
||||
io_connect_t connection;
|
||||
|
||||
kren_ret = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &connection);
|
||||
if (kren_ret == kIOReturnSuccess) {
|
||||
// IOByteCount size = sizeof(multiplier);
|
||||
|
||||
kren_ret = IOHIDGetAccelerationWithKey(connection, CFSTR(kIOHIDMouseAccelerationType), &sensitivity);
|
||||
if (kren_ret == kIOReturnSuccess) {
|
||||
// Calculate the greatest common factor.
|
||||
|
||||
unsigned long denominator = 1000000, d = denominator;
|
||||
unsigned long numerator = sensitivity * denominator, gcf = numerator;
|
||||
|
||||
while (d != 0) {
|
||||
unsigned long i = gcf % d;
|
||||
gcf = d;
|
||||
d = i;
|
||||
}
|
||||
|
||||
value = numerator / gcf;
|
||||
successful = true;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: IOHIDGetAccelerationWithKey: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_multi_click_time() {
|
||||
#if defined USE_IOKIT || defined USE_COREFOUNDATION || defined USE_CARBON_LEGACY
|
||||
bool successful = false;
|
||||
#if defined USE_IOKIT || defined USE_CARBON_LEGACY
|
||||
// This needs to be defined only if we have USE_IOKIT or USE_CARBON_LEGACY.
|
||||
SInt64 time;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
long int value = -1;
|
||||
|
||||
#ifdef USE_IOKIT
|
||||
if (!successful) {
|
||||
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
|
||||
if (service) {
|
||||
kern_return_t kren_ret = kIOReturnError;
|
||||
io_connect_t connection;
|
||||
|
||||
kren_ret = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &connection);
|
||||
if (kren_ret == kIOReturnSuccess) {
|
||||
IOByteCount size = sizeof(time);
|
||||
|
||||
kren_ret = IOHIDGetParameter(connection, CFSTR(kIOHIDClickTimeKey), (IOByteCount) sizeof(time), &time, &size);
|
||||
if (kren_ret == kIOReturnSuccess) {
|
||||
/* This is in some undefined unit of time that if we happen
|
||||
* to multiply by 900 gives us the time in milliseconds. We
|
||||
* add 0.5 to the result so that when we cast to long we
|
||||
* actually get a rounded result. Saves the math.h depend.
|
||||
*/
|
||||
value = (long) (900.0 * ((double) time) / 1000.0 / 1000.0 / 1000.0 + 0.5);
|
||||
successful = true;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: IOHIDGetParameter: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_COREFOUNDATION
|
||||
if (!successful) {
|
||||
Float32 clicktime;
|
||||
CFTypeRef pref_val = CFPreferencesCopyValue(CFSTR("com.apple.mouse.doubleClickThreshold"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
|
||||
if (pref_val != NULL && CFGetTypeID(pref_val) == CFNumberGetTypeID()) {
|
||||
if (CFNumberGetValue((CFNumberRef) pref_val, kCFNumberFloat32Type, &clicktime)) {
|
||||
/* This is in some undefined unit of time that if we happen
|
||||
* to multiply by 900 gives us the time in milliseconds. It is
|
||||
* completely possible that this value is in seconds and should be
|
||||
* multiplied by 1000 but because IOKit values are undocumented and
|
||||
* I have no idea what a Carbon 'tick' is so there really is no way
|
||||
* to confirm this.
|
||||
*/
|
||||
value = (long) (clicktime * 900);
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: CFPreferencesCopyValue: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_CARBON_LEGACY
|
||||
if (!successful) {
|
||||
// Apple documentation states that value is in 'ticks'. I am not sure
|
||||
// what that means, but it looks a lot like the arbitrary slider value.
|
||||
time = GetDblTime();
|
||||
if (time > -1) {
|
||||
// This is the slider value, we must multiply by 15 to convert to
|
||||
// milliseconds.
|
||||
value = (long) time * 15;
|
||||
successful = true;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: GetDblTime: %li.\n",
|
||||
__FUNCTION__, __LINE__, value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// Create a shared object constructor.
|
||||
__attribute__ ((constructor))
|
||||
void on_library_load() {
|
||||
// Initialize Native Input Functions.
|
||||
load_input_helper();
|
||||
}
|
||||
|
||||
// Create a shared object destructor.
|
||||
__attribute__ ((destructor))
|
||||
void on_library_unload() {
|
||||
// Disable the event hook.
|
||||
//hook_stop();
|
||||
|
||||
// Cleanup native input functions.
|
||||
unload_input_helper();
|
||||
}
|
441
vendor/github.com/robotn/gohook/hook/iohook.h
generated
vendored
Normal file
441
vendor/github.com/robotn/gohook/hook/iohook.h
generated
vendored
Normal file
@ -0,0 +1,441 @@
|
||||
|
||||
#ifndef __IOHOOK_H
|
||||
#define __IOHOOK_H
|
||||
|
||||
// #include "../../base/os.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Begin Error Codes */
|
||||
#define IOHOOK_SUCCESS 0x00
|
||||
#define IOHOOK_FAILURE 0x01
|
||||
|
||||
// System level errors.
|
||||
#define IOHOOK_ERROR_OUT_OF_MEMORY 0x02
|
||||
|
||||
// Unix specific errors.
|
||||
#define IOHOOK_ERROR_X_OPEN_DISPLAY 0x20
|
||||
#define IOHOOK_ERROR_X_RECORD_NOT_FOUND 0x21
|
||||
#define IOHOOK_ERROR_X_RECORD_ALLOC_RANGE 0x22
|
||||
#define IOHOOK_ERROR_X_RECORD_CREATE_CONTEXT 0x23
|
||||
#define IOHOOK_ERROR_X_RECORD_ENABLE_CONTEXT 0x24
|
||||
#define IOHOOK_ERROR_X_RECORD_GET_CONTEXT 0x25
|
||||
|
||||
// Windows specific errors.
|
||||
#define IOHOOK_ERROR_SET_WINDOWS_HOOK_EX 0x30
|
||||
#define IOHOOK_ERROR_GET_MODULE_HANDLE 0x31
|
||||
|
||||
// Darwin specific errors.
|
||||
#define IOHOOK_ERROR_AXAPI_DISABLED 0x40
|
||||
#define IOHOOK_ERROR_CREATE_EVENT_PORT 0x41
|
||||
#define IOHOOK_ERROR_CREATE_RUN_LOOP_SOURCE 0x42
|
||||
#define IOHOOK_ERROR_GET_RUNLOOP 0x43
|
||||
#define IOHOOK_ERROR_CREATE_OBSERVER 0x44
|
||||
/* End Error Codes */
|
||||
|
||||
/* Begin Log Levels and Function Prototype */
|
||||
typedef enum _log_level {
|
||||
LOG_LEVEL_DEBUG = 1,
|
||||
LOG_LEVEL_INFO,
|
||||
LOG_LEVEL_WARN,
|
||||
LOG_LEVEL_ERROR
|
||||
} log_level;
|
||||
|
||||
// Logger callback function prototype.
|
||||
typedef bool (*logger_t)(unsigned int, const char *, ...);
|
||||
/* End Log Levels and Function Prototype */
|
||||
|
||||
/* Begin Virtual Event Types and Data Structures */
|
||||
typedef enum _event_type {
|
||||
EVENT_HOOK_ENABLED = 1,
|
||||
EVENT_HOOK_DISABLED,
|
||||
EVENT_KEY_TYPED,
|
||||
EVENT_KEY_PRESSED,
|
||||
EVENT_KEY_RELEASED,
|
||||
EVENT_MOUSE_CLICKED,
|
||||
EVENT_MOUSE_PRESSED,
|
||||
EVENT_MOUSE_RELEASED,
|
||||
EVENT_MOUSE_MOVED,
|
||||
EVENT_MOUSE_DRAGGED,
|
||||
EVENT_MOUSE_WHEEL
|
||||
} event_type;
|
||||
|
||||
typedef struct _screen_data {
|
||||
uint8_t number;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
} screen_data;
|
||||
|
||||
typedef struct _keyboard_event_data {
|
||||
uint16_t keycode;
|
||||
uint16_t rawcode;
|
||||
uint16_t keychar;
|
||||
// char *keychar;
|
||||
} keyboard_event_data,
|
||||
key_pressed_event_data,
|
||||
key_released_event_data,
|
||||
key_typed_event_data;
|
||||
|
||||
typedef struct _mouse_event_data {
|
||||
uint16_t button;
|
||||
uint16_t clicks;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
} mouse_event_data,
|
||||
mouse_pressed_event_data,
|
||||
mouse_released_event_data,
|
||||
mouse_clicked_event_data;
|
||||
|
||||
typedef struct _mouse_wheel_event_data {
|
||||
uint16_t clicks;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
uint8_t type;
|
||||
uint16_t amount;
|
||||
int16_t rotation;
|
||||
uint8_t direction;
|
||||
} mouse_wheel_event_data;
|
||||
|
||||
typedef struct _iohook_event {
|
||||
event_type type;
|
||||
uint64_t time;
|
||||
uint16_t mask;
|
||||
uint16_t reserved;
|
||||
union {
|
||||
keyboard_event_data keyboard;
|
||||
mouse_event_data mouse;
|
||||
mouse_wheel_event_data wheel;
|
||||
} data;
|
||||
} iohook_event;
|
||||
|
||||
typedef void (*dispatcher_t)(iohook_event *const);
|
||||
/* End Virtual Event Types and Data Structures */
|
||||
|
||||
|
||||
/* Begin Virtual Key Codes */
|
||||
#define VC_ESCAPE 0x0001
|
||||
|
||||
// Begin Function Keys
|
||||
#define VC_F1 0x003B
|
||||
#define VC_F2 0x003C
|
||||
#define VC_F3 0x003D
|
||||
#define VC_F4 0x003E
|
||||
#define VC_F5 0x003F
|
||||
#define VC_F6 0x0040
|
||||
#define VC_F7 0x0041
|
||||
#define VC_F8 0x0042
|
||||
#define VC_F9 0x0043
|
||||
#define VC_F10 0x0044
|
||||
#define VC_F11 0x0057
|
||||
#define VC_F12 0x0058
|
||||
|
||||
#define VC_F13 0x005B
|
||||
#define VC_F14 0x005C
|
||||
#define VC_F15 0x005D
|
||||
#define VC_F16 0x0063
|
||||
#define VC_F17 0x0064
|
||||
#define VC_F18 0x0065
|
||||
#define VC_F19 0x0066
|
||||
#define VC_F20 0x0067
|
||||
#define VC_F21 0x0068
|
||||
#define VC_F22 0x0069
|
||||
#define VC_F23 0x006A
|
||||
#define VC_F24 0x006B
|
||||
// End Function Keys
|
||||
|
||||
|
||||
// Begin Alphanumeric Zone
|
||||
#define VC_BACKQUOTE 0x0029
|
||||
|
||||
#define VC_1 0x0002
|
||||
#define VC_2 0x0003
|
||||
#define VC_3 0x0004
|
||||
#define VC_4 0x0005
|
||||
#define VC_5 0x0006
|
||||
#define VC_6 0x0007
|
||||
#define VC_7 0x0008
|
||||
#define VC_8 0x0009
|
||||
#define VC_9 0x000A
|
||||
#define VC_0 0x000B
|
||||
|
||||
#define VC_MINUS 0x000C // '-'
|
||||
#define VC_EQUALS 0x000D // '='
|
||||
#define VC_BACKSPACE 0x000E
|
||||
|
||||
#define VC_TAB 0x000F
|
||||
#define VC_CAPS_LOCK 0x003A
|
||||
|
||||
#define VC_A 0x001E
|
||||
#define VC_B 0x0030
|
||||
#define VC_C 0x002E
|
||||
#define VC_D 0x0020
|
||||
#define VC_E 0x0012
|
||||
#define VC_F 0x0021
|
||||
#define VC_G 0x0022
|
||||
#define VC_H 0x0023
|
||||
#define VC_I 0x0017
|
||||
#define VC_J 0x0024
|
||||
#define VC_K 0x0025
|
||||
#define VC_L 0x0026
|
||||
#define VC_M 0x0032
|
||||
#define VC_N 0x0031
|
||||
#define VC_O 0x0018
|
||||
#define VC_P 0x0019
|
||||
#define VC_Q 0x0010
|
||||
#define VC_R 0x0013
|
||||
#define VC_S 0x001F
|
||||
#define VC_T 0x0014
|
||||
#define VC_U 0x0016
|
||||
#define VC_V 0x002F
|
||||
#define VC_W 0x0011
|
||||
#define VC_X 0x002D
|
||||
#define VC_Y 0x0015
|
||||
#define VC_Z 0x002C
|
||||
|
||||
#define VC_OPEN_BRACKET 0x001A // '['
|
||||
#define VC_CLOSE_BRACKET 0x001B // ']'
|
||||
#define VC_BACK_SLASH 0x002B // '\'
|
||||
|
||||
#define VC_SEMICOLON 0x0027 // ';'
|
||||
#define VC_QUOTE 0x0028
|
||||
#define VC_ENTER 0x001C
|
||||
|
||||
#define VC_COMMA 0x0033 // ','
|
||||
#define VC_PERIOD 0x0034 // '.'
|
||||
#define VC_SLASH 0x0035 // '/'
|
||||
|
||||
#define VC_SPACE 0x0039
|
||||
// End Alphanumeric Zone
|
||||
|
||||
|
||||
#define VC_PRINTSCREEN 0x0E37
|
||||
#define VC_SCROLL_LOCK 0x0046
|
||||
#define VC_PAUSE 0x0E45
|
||||
|
||||
|
||||
// Begin Edit Key Zone
|
||||
#define VC_INSERT 0x0E52
|
||||
#define VC_DELETE 0x0E53
|
||||
#define VC_HOME 0x0E47
|
||||
#define VC_END 0x0E4F
|
||||
#define VC_PAGE_UP 0x0E49
|
||||
#define VC_PAGE_DOWN 0x0E51
|
||||
// End Edit Key Zone
|
||||
|
||||
|
||||
// Begin Cursor Key Zone
|
||||
#define VC_UP 0xE048
|
||||
#define VC_LEFT 0xE04B
|
||||
#define VC_CLEAR 0xE04C
|
||||
#define VC_RIGHT 0xE04D
|
||||
#define VC_DOWN 0xE050
|
||||
// End Cursor Key Zone
|
||||
|
||||
|
||||
// Begin Numeric Zone
|
||||
#define VC_NUM_LOCK 0x0045
|
||||
#define VC_KP_DIVIDE 0x0E35
|
||||
#define VC_KP_MULTIPLY 0x0037
|
||||
#define VC_KP_SUBTRACT 0x004A
|
||||
#define VC_KP_EQUALS 0x0E0D
|
||||
#define VC_KP_ADD 0x004E
|
||||
#define VC_KP_ENTER 0x0E1C
|
||||
#define VC_KP_SEPARATOR 0x0053
|
||||
|
||||
#define VC_KP_1 0x004F
|
||||
#define VC_KP_2 0x0050
|
||||
#define VC_KP_3 0x0051
|
||||
#define VC_KP_4 0x004B
|
||||
#define VC_KP_5 0x004C
|
||||
#define VC_KP_6 0x004D
|
||||
#define VC_KP_7 0x0047
|
||||
#define VC_KP_8 0x0048
|
||||
#define VC_KP_9 0x0049
|
||||
#define VC_KP_0 0x0052
|
||||
|
||||
#define VC_KP_END 0xEE00 | VC_KP_1
|
||||
#define VC_KP_DOWN 0xEE00 | VC_KP_2
|
||||
#define VC_KP_PAGE_DOWN 0xEE00 | VC_KP_3
|
||||
#define VC_KP_LEFT 0xEE00 | VC_KP_4
|
||||
#define VC_KP_CLEAR 0xEE00 | VC_KP_5
|
||||
#define VC_KP_RIGHT 0xEE00 | VC_KP_6
|
||||
#define VC_KP_HOME 0xEE00 | VC_KP_7
|
||||
#define VC_KP_UP 0xEE00 | VC_KP_8
|
||||
#define VC_KP_PAGE_UP 0xEE00 | VC_KP_9
|
||||
#define VC_KP_INSERT 0xEE00 | VC_KP_0
|
||||
#define VC_KP_DELETE 0xEE00 | VC_KP_SEPARATOR
|
||||
// End Numeric Zone
|
||||
|
||||
|
||||
// Begin Modifier and Control Keys
|
||||
#define VC_SHIFT_L 0x002A
|
||||
#define VC_SHIFT_R 0x0036
|
||||
#define VC_CONTROL_L 0x001D
|
||||
#define VC_CONTROL_R 0x0E1D
|
||||
#define VC_ALT_L 0x0038 // Option or Alt Key
|
||||
#define VC_ALT_R 0x0E38 // Option or Alt Key
|
||||
#define VC_META_L 0x0E5B // Windows or Command Key
|
||||
#define VC_META_R 0x0E5C // Windows or Command Key
|
||||
#define VC_CONTEXT_MENU 0x0E5D
|
||||
// End Modifier and Control Keys
|
||||
|
||||
|
||||
// Begin Media Control Keys
|
||||
#define VC_POWER 0xE05E
|
||||
#define VC_SLEEP 0xE05F
|
||||
#define VC_WAKE 0xE063
|
||||
|
||||
#define VC_MEDIA_PLAY 0xE022
|
||||
#define VC_MEDIA_STOP 0xE024
|
||||
#define VC_MEDIA_PREVIOUS 0xE010
|
||||
#define VC_MEDIA_NEXT 0xE019
|
||||
#define VC_MEDIA_SELECT 0xE06D
|
||||
#define VC_MEDIA_EJECT 0xE02C
|
||||
|
||||
#define VC_VOLUME_MUTE 0xE020
|
||||
#define VC_VOLUME_UP 0xE030
|
||||
#define VC_VOLUME_DOWN 0xE02E
|
||||
|
||||
#define VC_APP_MAIL 0xE06C
|
||||
#define VC_APP_CALCULATOR 0xE021
|
||||
#define VC_APP_MUSIC 0xE03C
|
||||
#define VC_APP_PICTURES 0xE064
|
||||
|
||||
#define VC_BROWSER_SEARCH 0xE065
|
||||
#define VC_BROWSER_HOME 0xE032
|
||||
#define VC_BROWSER_BACK 0xE06A
|
||||
#define VC_BROWSER_FORWARD 0xE069
|
||||
#define VC_BROWSER_STOP 0xE068
|
||||
#define VC_BROWSER_REFRESH 0xE067
|
||||
#define VC_BROWSER_FAVORITES 0xE066
|
||||
// End Media Control Keys
|
||||
|
||||
// Begin Japanese Language Keys
|
||||
#define VC_KATAKANA 0x0070
|
||||
#define VC_UNDERSCORE 0x0073
|
||||
#define VC_FURIGANA 0x0077
|
||||
#define VC_KANJI 0x0079
|
||||
#define VC_HIRAGANA 0x007B
|
||||
#define VC_YEN 0x007D
|
||||
#define VC_KP_COMMA 0x007E
|
||||
// End Japanese Language Keys
|
||||
|
||||
// Begin Sun keyboards
|
||||
#define VC_SUN_HELP 0xFF75
|
||||
|
||||
#define VC_SUN_STOP 0xFF78
|
||||
#define VC_SUN_PROPS 0xFF76
|
||||
#define VC_SUN_FRONT 0xFF77
|
||||
#define VC_SUN_OPEN 0xFF74
|
||||
#define VC_SUN_FIND 0xFF7E
|
||||
#define VC_SUN_AGAIN 0xFF79
|
||||
#define VC_SUN_UNDO 0xFF7A
|
||||
#define VC_SUN_COPY 0xFF7C
|
||||
#define VC_SUN_INSERT 0xFF7D
|
||||
#define VC_SUN_CUT 0xFF7B
|
||||
// End Sun keyboards
|
||||
|
||||
#define VC_UNDEFINED 0x0000 // KeyCode Unknown
|
||||
|
||||
#define CHAR_UNDEFINED 0xFFFF // CharCode Unknown
|
||||
/* End Virtual Key Codes */
|
||||
|
||||
|
||||
/* Begin Virtual Modifier Masks */
|
||||
#define MASK_SHIFT_L 1 << 0
|
||||
#define MASK_CTRL_L 1 << 1
|
||||
#define MASK_META_L 1 << 2
|
||||
#define MASK_ALT_L 1 << 3
|
||||
|
||||
#define MASK_SHIFT_R 1 << 4
|
||||
#define MASK_CTRL_R 1 << 5
|
||||
#define MASK_META_R 1 << 6
|
||||
#define MASK_ALT_R 1 << 7
|
||||
|
||||
#define MASK_SHIFT MASK_SHIFT_L | MASK_SHIFT_R
|
||||
#define MASK_CTRL MASK_CTRL_L | MASK_CTRL_R
|
||||
#define MASK_META MASK_META_L | MASK_META_R
|
||||
#define MASK_ALT MASK_ALT_L | MASK_ALT_R
|
||||
|
||||
#define MASK_BUTTON1 1 << 8
|
||||
#define MASK_BUTTON2 1 << 9
|
||||
#define MASK_BUTTON3 1 << 10
|
||||
#define MASK_BUTTON4 1 << 11
|
||||
#define MASK_BUTTON5 1 << 12
|
||||
|
||||
#define MASK_NUM_LOCK 1 << 13
|
||||
#define MASK_CAPS_LOCK 1 << 14
|
||||
#define MASK_SCROLL_LOCK 1 << 15
|
||||
/* End Virtual Modifier Masks */
|
||||
|
||||
|
||||
/* Begin Virtual Mouse Buttons */
|
||||
#define MOUSE_NOBUTTON 0 // Any Button
|
||||
#define MOUSE_BUTTON1 1 // Left Button
|
||||
#define MOUSE_BUTTON2 2 // Right Button
|
||||
#define MOUSE_BUTTON3 3 // Middle Button
|
||||
#define MOUSE_BUTTON4 4 // Extra Mouse Button
|
||||
#define MOUSE_BUTTON5 5 // Extra Mouse Button
|
||||
|
||||
#define WHEEL_UNIT_SCROLL 1
|
||||
#define WHEEL_BLOCK_SCROLL 2
|
||||
|
||||
#define WHEEL_VERTICAL_DIRECTION 3
|
||||
#define WHEEL_HORIZONTAL_DIRECTION 4
|
||||
/* End Virtual Mouse Buttons */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IOHOOK_API __declspec(dllexport)
|
||||
#else
|
||||
#define IOHOOK_API
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Set the logger callback functions.
|
||||
IOHOOK_API void hook_set_logger_proc(logger_t logger_proc);
|
||||
|
||||
// Send a virtual event back to the system.
|
||||
IOHOOK_API void hook_post_event(iohook_event * const event);
|
||||
|
||||
// Set the event callback function.
|
||||
IOHOOK_API void hook_set_dispatch_proc(dispatcher_t dispatch_proc);
|
||||
|
||||
// Insert the event hook.
|
||||
IOHOOK_API int hook_run();
|
||||
|
||||
// Withdraw the event hook.
|
||||
IOHOOK_API int hook_stop();
|
||||
|
||||
// Retrieves an array of screen data for each available monitor.
|
||||
IOHOOK_API screen_data* hook_create_screen_info(unsigned char *count);
|
||||
|
||||
// Retrieves the keyboard auto repeat rate.
|
||||
IOHOOK_API long int hook_get_auto_repeat_rate();
|
||||
|
||||
// Retrieves the keyboard auto repeat delay.
|
||||
IOHOOK_API long int hook_get_auto_repeat_delay();
|
||||
|
||||
// Retrieves the mouse acceleration multiplier.
|
||||
IOHOOK_API long int hook_get_pointer_acceleration_multiplier();
|
||||
|
||||
// Retrieves the mouse acceleration threshold.
|
||||
IOHOOK_API long int hook_get_pointer_acceleration_threshold();
|
||||
|
||||
// Retrieves the mouse sensitivity.
|
||||
IOHOOK_API long int hook_get_pointer_sensitivity();
|
||||
|
||||
// Retrieves the double/triple click interval.
|
||||
IOHOOK_API long int hook_get_multi_click_time();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
15
vendor/github.com/robotn/gohook/hook/logger.h
generated
vendored
Normal file
15
vendor/github.com/robotn/gohook/hook/logger.h
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
#ifndef _included_logger
|
||||
#define _included_logger
|
||||
|
||||
#include "iohook.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef __FUNCTION__
|
||||
#define __FUNCTION__ __func__
|
||||
#endif
|
||||
|
||||
// logger(level, message)
|
||||
extern logger_t logger;
|
||||
|
||||
#endif
|
53
vendor/github.com/robotn/gohook/hook/logger_c.h
generated
vendored
Normal file
53
vendor/github.com/robotn/gohook/hook/logger_c.h
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "iohook.h"
|
||||
#include "logger.h"
|
||||
|
||||
static bool default_logger(unsigned int level, const char *format, ...) {
|
||||
bool status = false;
|
||||
|
||||
#ifndef USE_QUIET
|
||||
va_list args;
|
||||
switch (level) {
|
||||
#ifdef USE_DEBUG
|
||||
case LOG_LEVEL_DEBUG:
|
||||
#endif
|
||||
case LOG_LEVEL_INFO:
|
||||
va_start(args, format);
|
||||
status = vfprintf(stdout, format, args) >= 0;
|
||||
va_end(args);
|
||||
break;
|
||||
|
||||
case LOG_LEVEL_WARN:
|
||||
case LOG_LEVEL_ERROR:
|
||||
va_start(args, format);
|
||||
status = vfprintf(stderr, format, args) >= 0;
|
||||
va_end(args);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Current logger function pointer, this should never be null.
|
||||
// FIXME This should be static and wrapped with a public facing function.
|
||||
logger_t logger = &default_logger;
|
||||
|
||||
|
||||
IOHOOK_API void hookSetlogger(logger_t logger_proc) {
|
||||
if (logger_proc == NULL) {
|
||||
logger = &default_logger;
|
||||
}
|
||||
else {
|
||||
logger = logger_proc;
|
||||
}
|
||||
}
|
328
vendor/github.com/robotn/gohook/hook/windows/event_c.h
generated
vendored
Normal file
328
vendor/github.com/robotn/gohook/hook/windows/event_c.h
generated
vendored
Normal file
@ -0,0 +1,328 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../iohook.h"
|
||||
#include <windows.h>
|
||||
|
||||
// #include "logger.h"
|
||||
#include "input.h"
|
||||
|
||||
// Some buggy versions of MinGW and MSys do not include these constants in winuser.h.
|
||||
#ifndef MAPVK_VK_TO_VSC
|
||||
#define MAPVK_VK_TO_VSC 0
|
||||
#define MAPVK_VSC_TO_VK 1
|
||||
#define MAPVK_VK_TO_CHAR 2
|
||||
#define MAPVK_VSC_TO_VK_EX 3
|
||||
#endif
|
||||
// Some buggy versions of MinGW and MSys only define this value for Windows
|
||||
// versions >= 0x0600 (Windows Vista) when it should be 0x0500 (Windows 2000).
|
||||
#ifndef MAPVK_VK_TO_VSC_EX
|
||||
#define MAPVK_VK_TO_VSC_EX 4
|
||||
#endif
|
||||
|
||||
#ifndef KEYEVENTF_SCANCODE
|
||||
#define KEYEVENTF_EXTENDEDKEY 0x0001
|
||||
#define KEYEVENTF_KEYUP 0x0002
|
||||
#define KEYEVENTF_UNICODE 0x0004
|
||||
#define KEYEVENTF_SCANCODE 0x0008
|
||||
#endif
|
||||
|
||||
#ifndef KEYEVENTF_KEYDOWN
|
||||
#define KEYEVENTF_KEYDOWN 0x0000
|
||||
#endif
|
||||
|
||||
#define MAX_WINDOWS_COORD_VALUE 65535
|
||||
|
||||
static UINT keymask_lookup[8] = {
|
||||
VK_LSHIFT,
|
||||
VK_LCONTROL,
|
||||
VK_LWIN,
|
||||
VK_LMENU,
|
||||
|
||||
VK_RSHIFT,
|
||||
VK_RCONTROL,
|
||||
VK_RWIN,
|
||||
VK_RMENU
|
||||
};
|
||||
|
||||
IOHOOK_API void hook_post_event(iohook_event * const event) {
|
||||
//FIXME implement multiple monitor support
|
||||
uint16_t screen_width = GetSystemMetrics( SM_CXSCREEN );
|
||||
uint16_t screen_height = GetSystemMetrics( SM_CYSCREEN );
|
||||
|
||||
unsigned char events_size = 0, events_max = 28;
|
||||
INPUT *events = malloc(sizeof(INPUT) * events_max);
|
||||
|
||||
if (event->mask & (MASK_SHIFT | MASK_CTRL | MASK_META | MASK_ALT)) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(keymask_lookup) / sizeof(UINT); i++) {
|
||||
if (event->mask & 1 << i) {
|
||||
events[events_size].type = INPUT_KEYBOARD;
|
||||
events[events_size].ki.wVk = keymask_lookup[i];
|
||||
events[events_size].ki.dwFlags = KEYEVENTF_KEYDOWN;
|
||||
events[events_size].ki.time = 0; // Use current system time.
|
||||
events_size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event->mask & (MASK_BUTTON1 | MASK_BUTTON2 | MASK_BUTTON3 | MASK_BUTTON4 | MASK_BUTTON5)) {
|
||||
events[events_size].type = INPUT_MOUSE;
|
||||
events[events_size].mi.dx = 0; // Relative mouse movement due to
|
||||
events[events_size].mi.dy = 0; // MOUSEEVENTF_ABSOLUTE not being set.
|
||||
events[events_size].mi.mouseData = 0x00;
|
||||
events[events_size].mi.time = 0; // Use current system time.
|
||||
|
||||
if (event->mask & MASK_BUTTON1) {
|
||||
events[events_size].mi.mouseData |= MOUSEEVENTF_LEFTDOWN;
|
||||
}
|
||||
|
||||
if (event->mask & MASK_BUTTON2) {
|
||||
events[events_size].mi.mouseData |= MOUSEEVENTF_RIGHTDOWN;
|
||||
}
|
||||
|
||||
if (event->mask & MASK_BUTTON3) {
|
||||
events[events_size].mi.mouseData |= MOUSEEVENTF_MIDDLEDOWN;
|
||||
}
|
||||
|
||||
if (event->mask & MASK_BUTTON4) {
|
||||
events[events_size].mi.mouseData = XBUTTON1;
|
||||
events[events_size].mi.mouseData |= MOUSEEVENTF_XDOWN;
|
||||
}
|
||||
|
||||
if (event->mask & MASK_BUTTON5) {
|
||||
events[events_size].mi.mouseData = XBUTTON2;
|
||||
events[events_size].mi.dwFlags |= MOUSEEVENTF_XDOWN;
|
||||
}
|
||||
|
||||
events_size++;
|
||||
}
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case EVENT_KEY_PRESSED:
|
||||
events[events_size].ki.wVk = scancode_to_keycode(event->data.keyboard.keycode);
|
||||
if (events[events_size].ki.wVk != 0x0000) {
|
||||
events[events_size].type = INPUT_KEYBOARD;
|
||||
events[events_size].ki.dwFlags = KEYEVENTF_KEYDOWN; // |= KEYEVENTF_SCANCODE;
|
||||
events[events_size].ki.wScan = 0; // event->data.keyboard.keycode;
|
||||
events[events_size].ki.time = 0; // GetSystemTime()
|
||||
events_size++;
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Unable to lookup scancode: %li\n",
|
||||
__FUNCTION__, __LINE__,
|
||||
event->data.keyboard.keycode);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_KEY_RELEASED:
|
||||
events[events_size].ki.wVk = scancode_to_keycode(event->data.keyboard.keycode);
|
||||
if (events[events_size].ki.wVk != 0x0000) {
|
||||
events[events_size].type = INPUT_KEYBOARD;
|
||||
events[events_size].ki.dwFlags = KEYEVENTF_KEYUP; // |= KEYEVENTF_SCANCODE;
|
||||
events[events_size].ki.wVk = scancode_to_keycode(event->data.keyboard.keycode);
|
||||
events[events_size].ki.wScan = 0; // event->data.keyboard.keycode;
|
||||
events[events_size].ki.time = 0; // GetSystemTime()
|
||||
events_size++;
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Unable to lookup scancode: %li\n",
|
||||
__FUNCTION__, __LINE__,
|
||||
event->data.keyboard.keycode);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case EVENT_MOUSE_PRESSED:
|
||||
events[events_size].type = INPUT_MOUSE;
|
||||
events[events_size].mi.dwFlags = MOUSEEVENTF_XDOWN;
|
||||
|
||||
switch (event->data.mouse.button) {
|
||||
case MOUSE_BUTTON1:
|
||||
events[events_size].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
|
||||
break;
|
||||
|
||||
case MOUSE_BUTTON2:
|
||||
events[events_size].mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
|
||||
break;
|
||||
|
||||
case MOUSE_BUTTON3:
|
||||
events[events_size].mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN;
|
||||
break;
|
||||
|
||||
case MOUSE_BUTTON4:
|
||||
events[events_size].mi.mouseData = XBUTTON1;
|
||||
break;
|
||||
|
||||
case MOUSE_BUTTON5:
|
||||
events[events_size].mi.mouseData = XBUTTON2;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Extra buttons.
|
||||
if (event->data.mouse.button > 3) {
|
||||
events[events_size].mi.mouseData = event->data.mouse.button - 3;
|
||||
}
|
||||
}
|
||||
|
||||
events[events_size].mi.dx = event->data.mouse.x * (MAX_WINDOWS_COORD_VALUE / screen_width) + 1;
|
||||
events[events_size].mi.dy = event->data.mouse.y * (MAX_WINDOWS_COORD_VALUE / screen_height) + 1;
|
||||
|
||||
events[events_size].mi.dwFlags |= MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
|
||||
events[events_size].mi.time = 0; // GetSystemTime()
|
||||
|
||||
events_size++;
|
||||
break;
|
||||
|
||||
case EVENT_MOUSE_RELEASED:
|
||||
events[events_size].type = INPUT_MOUSE;
|
||||
events[events_size].mi.dwFlags = MOUSEEVENTF_XUP;
|
||||
|
||||
switch (event->data.mouse.button) {
|
||||
case MOUSE_BUTTON1:
|
||||
events[events_size].mi.dwFlags = MOUSEEVENTF_LEFTUP;
|
||||
break;
|
||||
|
||||
case MOUSE_BUTTON2:
|
||||
events[events_size].mi.dwFlags = MOUSEEVENTF_RIGHTUP;
|
||||
break;
|
||||
|
||||
case MOUSE_BUTTON3:
|
||||
events[events_size].mi.dwFlags = MOUSEEVENTF_MIDDLEUP;
|
||||
break;
|
||||
|
||||
case MOUSE_BUTTON4:
|
||||
events[events_size].mi.mouseData = XBUTTON1;
|
||||
break;
|
||||
|
||||
case MOUSE_BUTTON5:
|
||||
events[events_size].mi.mouseData = XBUTTON2;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Extra buttons.
|
||||
if (event->data.mouse.button > 3) {
|
||||
events[events_size].mi.mouseData = event->data.mouse.button - 3;
|
||||
}
|
||||
}
|
||||
|
||||
events[events_size].mi.dx = event->data.mouse.x * (MAX_WINDOWS_COORD_VALUE / screen_width) + 1;
|
||||
events[events_size].mi.dy = event->data.mouse.y * (MAX_WINDOWS_COORD_VALUE / screen_height) + 1;
|
||||
|
||||
events[events_size].mi.dwFlags |= MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
|
||||
events[events_size].mi.time = 0; // GetSystemTime()
|
||||
events_size++;
|
||||
break;
|
||||
|
||||
|
||||
case EVENT_MOUSE_WHEEL:
|
||||
events[events_size].type = INPUT_MOUSE;
|
||||
events[events_size].mi.dwFlags = MOUSEEVENTF_WHEEL;
|
||||
|
||||
// type, amount and rotation?
|
||||
events[events_size].mi.mouseData = event->data.wheel.amount * event->data.wheel.rotation * WHEEL_DELTA;
|
||||
|
||||
events[events_size].mi.dx = event->data.wheel.x * (MAX_WINDOWS_COORD_VALUE / screen_width) + 1;
|
||||
events[events_size].mi.dy = event->data.wheel.y * (MAX_WINDOWS_COORD_VALUE / screen_height) + 1;
|
||||
|
||||
events[events_size].mi.dwFlags |= MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
|
||||
events[events_size].mi.time = 0; // GetSystemTime()
|
||||
events_size++;
|
||||
break;
|
||||
|
||||
|
||||
case EVENT_MOUSE_DRAGGED:
|
||||
// The button masks are all applied with the modifier masks.
|
||||
|
||||
case EVENT_MOUSE_MOVED:
|
||||
events[events_size].type = INPUT_MOUSE;
|
||||
events[events_size].mi.dwFlags = MOUSEEVENTF_MOVE;
|
||||
|
||||
events[events_size].mi.dx = event->data.mouse.x * (MAX_WINDOWS_COORD_VALUE / screen_width) + 1;
|
||||
events[events_size].mi.dy = event->data.mouse.y * (MAX_WINDOWS_COORD_VALUE / screen_height) + 1;
|
||||
|
||||
events[events_size].mi.dwFlags |= MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
|
||||
events[events_size].mi.time = 0; // GetSystemTime()
|
||||
events_size++;
|
||||
break;
|
||||
|
||||
|
||||
case EVENT_MOUSE_CLICKED:
|
||||
case EVENT_KEY_TYPED:
|
||||
// Ignore clicked and typed events.
|
||||
|
||||
case EVENT_HOOK_ENABLED:
|
||||
case EVENT_HOOK_DISABLED:
|
||||
// Ignore hook enabled / disabled events.
|
||||
|
||||
default:
|
||||
// Ignore any other garbage.
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: Ignoring post event type %#X\n",
|
||||
__FUNCTION__, __LINE__, event->type);
|
||||
break;
|
||||
}
|
||||
|
||||
// Release the previously held modifier keys used to fake the event mask.
|
||||
if (event->mask & (MASK_SHIFT | MASK_CTRL | MASK_META | MASK_ALT)) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(keymask_lookup) / sizeof(UINT); i++) {
|
||||
if (event->mask & 1 << i) {
|
||||
events[events_size].type = INPUT_KEYBOARD;
|
||||
events[events_size].ki.wVk = keymask_lookup[i];
|
||||
events[events_size].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
events[events_size].ki.time = 0; // Use current system time.
|
||||
events_size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event->mask & (MASK_BUTTON1 | MASK_BUTTON2 | MASK_BUTTON3 | MASK_BUTTON4 | MASK_BUTTON5)) {
|
||||
events[events_size].type = INPUT_MOUSE;
|
||||
events[events_size].mi.dx = 0; // Relative mouse movement due to
|
||||
events[events_size].mi.dy = 0; // MOUSEEVENTF_ABSOLUTE not being set.
|
||||
events[events_size].mi.mouseData = 0x00;
|
||||
events[events_size].mi.time = 0; // Use current system time.
|
||||
|
||||
// If dwFlags does not contain MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, or MOUSEEVENTF_XUP,
|
||||
// then mouseData should be zero.
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646273%28v=vs.85%29.aspx
|
||||
if (event->mask & MASK_BUTTON1) {
|
||||
events[events_size].mi.dwFlags |= MOUSEEVENTF_LEFTUP;
|
||||
}
|
||||
|
||||
if (event->mask & MASK_BUTTON2) {
|
||||
events[events_size].mi.dwFlags |= MOUSEEVENTF_RIGHTUP;
|
||||
}
|
||||
|
||||
if (event->mask & MASK_BUTTON3) {
|
||||
events[events_size].mi.dwFlags |= MOUSEEVENTF_MIDDLEUP;
|
||||
}
|
||||
|
||||
if (event->mask & MASK_BUTTON4) {
|
||||
events[events_size].mi.mouseData = XBUTTON1;
|
||||
events[events_size].mi.dwFlags |= MOUSEEVENTF_XUP;
|
||||
}
|
||||
|
||||
if (event->mask & MASK_BUTTON5) {
|
||||
events[events_size].mi.mouseData = XBUTTON2;
|
||||
events[events_size].mi.dwFlags |= MOUSEEVENTF_XUP;
|
||||
}
|
||||
|
||||
events_size++;
|
||||
}
|
||||
|
||||
// Create the key release input
|
||||
// memcpy(key_events + 1, key_events, sizeof(INPUT));
|
||||
// key_events[1].ki.dwFlags |= KEYEVENTF_KEYUP;
|
||||
|
||||
if (! SendInput(events_size, events, sizeof(INPUT)) ) {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: SendInput() failed! (%#lX)\n",
|
||||
__FUNCTION__, __LINE__, (unsigned long) GetLastError());
|
||||
}
|
||||
|
||||
free(events);
|
||||
}
|
747
vendor/github.com/robotn/gohook/hook/windows/hook_c.h
generated
vendored
Normal file
747
vendor/github.com/robotn/gohook/hook/windows/hook_c.h
generated
vendored
Normal file
@ -0,0 +1,747 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "../iohook.h"
|
||||
#include "input.h"
|
||||
// #include "logger.h"
|
||||
|
||||
// Thread and hook handles.
|
||||
static DWORD hook_thread_id = 0;
|
||||
static HHOOK keyboard_event_hhook = NULL, mouse_event_hhook = NULL;
|
||||
static HWINEVENTHOOK win_event_hhook = NULL;
|
||||
|
||||
// The handle to the DLL module pulled in DllMain on DLL_PROCESS_ATTACH.
|
||||
extern HINSTANCE hInst;
|
||||
|
||||
// Modifiers for tracking key masks.
|
||||
static unsigned short int current_modifiers = 0x0000;
|
||||
|
||||
// Click count globals.
|
||||
static unsigned short click_count = 0;
|
||||
static DWORD click_time = 0;
|
||||
static unsigned short int click_button = MOUSE_NOBUTTON;
|
||||
static POINT last_click;
|
||||
|
||||
// Static event memory.
|
||||
static iohook_event event;
|
||||
|
||||
// Event dispatch callback.
|
||||
static dispatcher_t dispatcher = NULL;
|
||||
|
||||
IOHOOK_API void hook_set_dispatch_proc(dispatcher_t dispatch_proc) {
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Setting new dispatch callback to %#p.\n",
|
||||
__FUNCTION__, __LINE__, dispatch_proc);
|
||||
|
||||
dispatcher = dispatch_proc;
|
||||
}
|
||||
|
||||
// Send out an event if a dispatcher was set.
|
||||
static inline void dispatch_event(iohook_event *const event) {
|
||||
if (dispatcher != NULL) {
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Dispatching event type %u.\n",
|
||||
__FUNCTION__, __LINE__, event->type);
|
||||
|
||||
dispatcher(event);
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: No dispatch callback set!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set the native modifier mask for future events.
|
||||
static inline void set_modifier_mask(unsigned short int mask) {
|
||||
current_modifiers |= mask;
|
||||
}
|
||||
|
||||
// Unset the native modifier mask for future events.
|
||||
static inline void unset_modifier_mask(unsigned short int mask) {
|
||||
current_modifiers ^= mask;
|
||||
}
|
||||
|
||||
// Get the current native modifier mask state.
|
||||
static inline unsigned short int get_modifiers() {
|
||||
return current_modifiers;
|
||||
}
|
||||
|
||||
// Initialize the modifier mask to the current modifiers.
|
||||
static void initialize_modifiers() {
|
||||
current_modifiers = 0x0000;
|
||||
|
||||
// NOTE We are checking the high order bit, so it will be < 0 for a singed short.
|
||||
if (GetKeyState(VK_LSHIFT) < 0) { set_modifier_mask(MASK_SHIFT_L); }
|
||||
if (GetKeyState(VK_RSHIFT) < 0) { set_modifier_mask(MASK_SHIFT_R); }
|
||||
if (GetKeyState(VK_LCONTROL) < 0) { set_modifier_mask(MASK_CTRL_L); }
|
||||
if (GetKeyState(VK_RCONTROL) < 0) { set_modifier_mask(MASK_CTRL_R); }
|
||||
if (GetKeyState(VK_LMENU) < 0) { set_modifier_mask(MASK_ALT_L); }
|
||||
if (GetKeyState(VK_RMENU) < 0) { set_modifier_mask(MASK_ALT_R); }
|
||||
if (GetKeyState(VK_LWIN) < 0) { set_modifier_mask(MASK_META_L); }
|
||||
if (GetKeyState(VK_RWIN) < 0) { set_modifier_mask(MASK_META_R); }
|
||||
|
||||
if (GetKeyState(VK_LBUTTON) < 0) { set_modifier_mask(MASK_BUTTON1); }
|
||||
if (GetKeyState(VK_RBUTTON) < 0) { set_modifier_mask(MASK_BUTTON2); }
|
||||
if (GetKeyState(VK_MBUTTON) < 0) { set_modifier_mask(MASK_BUTTON3); }
|
||||
if (GetKeyState(VK_XBUTTON1) < 0) { set_modifier_mask(MASK_BUTTON4); }
|
||||
if (GetKeyState(VK_XBUTTON2) < 0) { set_modifier_mask(MASK_BUTTON5); }
|
||||
|
||||
if (GetKeyState(VK_NUMLOCK) < 0) { set_modifier_mask(MASK_NUM_LOCK); }
|
||||
if (GetKeyState(VK_CAPITAL) < 0) { set_modifier_mask(MASK_CAPS_LOCK); }
|
||||
if (GetKeyState(VK_SCROLL) < 0) { set_modifier_mask(MASK_SCROLL_LOCK); }
|
||||
}
|
||||
|
||||
|
||||
/* Retrieves the mouse wheel scroll type. This function cannot be included as
|
||||
* part of the input.h due to platform specific calling restrictions.
|
||||
*/
|
||||
static unsigned short int get_scroll_wheel_type() {
|
||||
unsigned short int value;
|
||||
UINT wheel_type;
|
||||
|
||||
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &wheel_type, 0);
|
||||
if (wheel_type == WHEEL_PAGESCROLL) {
|
||||
value = WHEEL_BLOCK_SCROLL;
|
||||
}
|
||||
else {
|
||||
value = WHEEL_UNIT_SCROLL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Retrieves the mouse wheel scroll amount. This function cannot be included as
|
||||
* part of the input.h due to platform specific calling restrictions.
|
||||
*/
|
||||
static unsigned short int get_scroll_wheel_amount() {
|
||||
unsigned short int value;
|
||||
UINT wheel_amount;
|
||||
|
||||
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &wheel_amount, 0);
|
||||
if (wheel_amount == WHEEL_PAGESCROLL) {
|
||||
value = 1;
|
||||
}
|
||||
else {
|
||||
value = (unsigned short int) wheel_amount;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void unregister_running_hooks() {
|
||||
// Stop the event hook and any timer still running.
|
||||
if (win_event_hhook != NULL) {
|
||||
UnhookWinEvent(win_event_hhook);
|
||||
win_event_hhook = NULL;
|
||||
}
|
||||
|
||||
// Destroy the native hooks.
|
||||
if (keyboard_event_hhook != NULL) {
|
||||
UnhookWindowsHookEx(keyboard_event_hhook);
|
||||
keyboard_event_hhook = NULL;
|
||||
}
|
||||
|
||||
if (mouse_event_hhook != NULL) {
|
||||
UnhookWindowsHookEx(mouse_event_hhook);
|
||||
mouse_event_hhook = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void hook_start_proc() {
|
||||
// Get the local system time in UNIX epoch form.
|
||||
uint64_t timestamp = GetMessageTime();
|
||||
|
||||
// Populate the hook start event.
|
||||
event.time = timestamp;
|
||||
event.reserved = 0x00;
|
||||
|
||||
event.type = EVENT_HOOK_ENABLED;
|
||||
event.mask = 0x00;
|
||||
|
||||
// Fire the hook start event.
|
||||
dispatch_event(&event);
|
||||
}
|
||||
|
||||
void hook_stop_proc() {
|
||||
// Get the local system time in UNIX epoch form.
|
||||
uint64_t timestamp = GetMessageTime();
|
||||
|
||||
// Populate the hook stop event.
|
||||
event.time = timestamp;
|
||||
event.reserved = 0x00;
|
||||
|
||||
event.type = EVENT_HOOK_DISABLED;
|
||||
event.mask = 0x00;
|
||||
|
||||
// Fire the hook stop event.
|
||||
dispatch_event(&event);
|
||||
}
|
||||
|
||||
static void process_key_pressed(KBDLLHOOKSTRUCT *kbhook) {
|
||||
// Check and setup modifiers.
|
||||
if (kbhook->vkCode == VK_LSHIFT) { set_modifier_mask(MASK_SHIFT_L); }
|
||||
else if (kbhook->vkCode == VK_RSHIFT) { set_modifier_mask(MASK_SHIFT_R); }
|
||||
else if (kbhook->vkCode == VK_LCONTROL) { set_modifier_mask(MASK_CTRL_L); }
|
||||
else if (kbhook->vkCode == VK_RCONTROL) { set_modifier_mask(MASK_CTRL_R); }
|
||||
else if (kbhook->vkCode == VK_LMENU) { set_modifier_mask(MASK_ALT_L); }
|
||||
else if (kbhook->vkCode == VK_RMENU) { set_modifier_mask(MASK_ALT_R); }
|
||||
else if (kbhook->vkCode == VK_LWIN) { set_modifier_mask(MASK_META_L); }
|
||||
else if (kbhook->vkCode == VK_RWIN) { set_modifier_mask(MASK_META_R); }
|
||||
else if (kbhook->vkCode == VK_NUMLOCK) { set_modifier_mask(MASK_NUM_LOCK); }
|
||||
else if (kbhook->vkCode == VK_CAPITAL) { set_modifier_mask(MASK_CAPS_LOCK); }
|
||||
else if (kbhook->vkCode == VK_SCROLL) { set_modifier_mask(MASK_SCROLL_LOCK); }
|
||||
|
||||
// Populate key pressed event.
|
||||
event.time = kbhook->time;
|
||||
event.reserved = 0x00;
|
||||
|
||||
event.type = EVENT_KEY_PRESSED;
|
||||
event.mask = get_modifiers();
|
||||
|
||||
event.data.keyboard.keycode = keycode_to_scancode(kbhook->vkCode, kbhook->flags);
|
||||
event.data.keyboard.rawcode = kbhook->vkCode;
|
||||
event.data.keyboard.keychar = CHAR_UNDEFINED;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Key %#X pressed. (%#X)\n",
|
||||
__FUNCTION__, __LINE__, event.data.keyboard.keycode, event.data.keyboard.rawcode);
|
||||
|
||||
// Populate key pressed event.
|
||||
dispatch_event(&event);
|
||||
|
||||
// If the pressed event was not consumed...
|
||||
if (event.reserved ^ 0x01) {
|
||||
// Buffer for unicode typed chars. No more than 2 needed.
|
||||
WCHAR buffer[2]; // = { WCH_NONE };
|
||||
|
||||
// If the pressed event was not consumed and a unicode char exists...
|
||||
SIZE_T count = keycode_to_unicode(kbhook->vkCode, buffer, sizeof(buffer));
|
||||
unsigned int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
// Populate key typed event.
|
||||
event.time = kbhook->time;
|
||||
event.reserved = 0x00;
|
||||
|
||||
event.type = EVENT_KEY_TYPED;
|
||||
event.mask = get_modifiers();
|
||||
|
||||
event.data.keyboard.keycode = VC_UNDEFINED;
|
||||
event.data.keyboard.rawcode = kbhook->vkCode;
|
||||
event.data.keyboard.keychar = buffer[i];
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Key %#X typed. (%lc)\n",
|
||||
__FUNCTION__, __LINE__, event.data.keyboard.keycode, (wint_t) event.data.keyboard.keychar);
|
||||
|
||||
// Fire key typed event.
|
||||
dispatch_event(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void process_key_released(KBDLLHOOKSTRUCT *kbhook) {
|
||||
// Check and setup modifiers.
|
||||
if (kbhook->vkCode == VK_LSHIFT) { unset_modifier_mask(MASK_SHIFT_L); }
|
||||
else if (kbhook->vkCode == VK_RSHIFT) { unset_modifier_mask(MASK_SHIFT_R); }
|
||||
else if (kbhook->vkCode == VK_LCONTROL) { unset_modifier_mask(MASK_CTRL_L); }
|
||||
else if (kbhook->vkCode == VK_RCONTROL) { unset_modifier_mask(MASK_CTRL_R); }
|
||||
else if (kbhook->vkCode == VK_LMENU) { unset_modifier_mask(MASK_ALT_L); }
|
||||
else if (kbhook->vkCode == VK_RMENU) { unset_modifier_mask(MASK_ALT_R); }
|
||||
else if (kbhook->vkCode == VK_LWIN) { unset_modifier_mask(MASK_META_L); }
|
||||
else if (kbhook->vkCode == VK_RWIN) { unset_modifier_mask(MASK_META_R); }
|
||||
else if (kbhook->vkCode == VK_NUMLOCK) { unset_modifier_mask(MASK_NUM_LOCK); }
|
||||
else if (kbhook->vkCode == VK_CAPITAL) { unset_modifier_mask(MASK_CAPS_LOCK); }
|
||||
else if (kbhook->vkCode == VK_SCROLL) { unset_modifier_mask(MASK_SCROLL_LOCK); }
|
||||
|
||||
// Populate key pressed event.
|
||||
event.time = kbhook->time;
|
||||
event.reserved = 0x00;
|
||||
|
||||
event.type = EVENT_KEY_RELEASED;
|
||||
event.mask = get_modifiers();
|
||||
|
||||
event.data.keyboard.keycode = keycode_to_scancode(kbhook->vkCode, kbhook->flags);
|
||||
event.data.keyboard.rawcode = kbhook->vkCode;
|
||||
event.data.keyboard.keychar = CHAR_UNDEFINED;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Key %#X released. (%#X)\n",
|
||||
__FUNCTION__, __LINE__, event.data.keyboard.keycode, event.data.keyboard.rawcode);
|
||||
|
||||
// Fire key released event.
|
||||
dispatch_event(&event);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK keyboard_hook_event_proc(int nCode, WPARAM wParam, LPARAM lParam) {
|
||||
KBDLLHOOKSTRUCT *kbhook = (KBDLLHOOKSTRUCT *) lParam;
|
||||
switch (wParam) {
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
process_key_pressed(kbhook);
|
||||
break;
|
||||
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
process_key_released(kbhook);
|
||||
break;
|
||||
|
||||
default:
|
||||
// In theory this *should* never execute.
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Unhandled Windows keyboard event: %#X.\n",
|
||||
__FUNCTION__, __LINE__, (unsigned int) wParam);
|
||||
break;
|
||||
}
|
||||
|
||||
LRESULT hook_result = -1;
|
||||
if (nCode < 0 || event.reserved ^ 0x01) {
|
||||
hook_result = CallNextHookEx(keyboard_event_hhook, nCode, wParam, lParam);
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Consuming the current event. (%li)\n",
|
||||
__FUNCTION__, __LINE__, (long) hook_result);
|
||||
}
|
||||
|
||||
return hook_result;
|
||||
}
|
||||
|
||||
|
||||
static void process_button_pressed(MSLLHOOKSTRUCT *mshook, uint16_t button) {
|
||||
uint64_t timestamp = GetMessageTime();
|
||||
|
||||
// Track the number of clicks, the button must match the previous button.
|
||||
if (button == click_button && (long int) (timestamp - click_time) <= hook_get_multi_click_time()) {
|
||||
if (click_count < USHRT_MAX) {
|
||||
click_count++;
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: Click count overflow detected!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Reset the click count.
|
||||
click_count = 1;
|
||||
|
||||
// Set the previous button.
|
||||
click_button = button;
|
||||
}
|
||||
|
||||
// Save this events time to calculate the click_count.
|
||||
click_time = timestamp;
|
||||
|
||||
// Store the last click point.
|
||||
last_click.x = mshook->pt.x;
|
||||
last_click.y = mshook->pt.y;
|
||||
|
||||
// Populate mouse pressed event.
|
||||
event.time = timestamp;
|
||||
event.reserved = 0x00;
|
||||
|
||||
event.type = EVENT_MOUSE_PRESSED;
|
||||
event.mask = get_modifiers();
|
||||
|
||||
event.data.mouse.button = button;
|
||||
event.data.mouse.clicks = click_count;
|
||||
|
||||
event.data.mouse.x = mshook->pt.x;
|
||||
event.data.mouse.y = mshook->pt.y;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Button %u pressed %u time(s). (%u, %u)\n",
|
||||
__FUNCTION__, __LINE__, event.data.mouse.button, event.data.mouse.clicks,
|
||||
event.data.mouse.x, event.data.mouse.y);
|
||||
|
||||
// Fire mouse pressed event.
|
||||
dispatch_event(&event);
|
||||
}
|
||||
|
||||
static void process_button_released(MSLLHOOKSTRUCT *mshook, uint16_t button) {
|
||||
// Populate mouse released event.
|
||||
event.time = GetMessageTime();
|
||||
event.reserved = 0x00;
|
||||
|
||||
event.type = EVENT_MOUSE_RELEASED;
|
||||
event.mask = get_modifiers();
|
||||
|
||||
event.data.mouse.button = button;
|
||||
event.data.mouse.clicks = click_count;
|
||||
|
||||
event.data.mouse.x = mshook->pt.x;
|
||||
event.data.mouse.y = mshook->pt.y;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Button %u released %u time(s). (%u, %u)\n",
|
||||
__FUNCTION__, __LINE__, event.data.mouse.button,
|
||||
event.data.mouse.clicks,
|
||||
event.data.mouse.x, event.data.mouse.y);
|
||||
|
||||
// Fire mouse released event.
|
||||
dispatch_event(&event);
|
||||
|
||||
// If the pressed event was not consumed...
|
||||
if (event.reserved ^ 0x01 && last_click.x == mshook->pt.x && last_click.y == mshook->pt.y) {
|
||||
// Populate mouse clicked event.
|
||||
event.time = GetMessageTime();
|
||||
event.reserved = 0x00;
|
||||
|
||||
event.type = EVENT_MOUSE_CLICKED;
|
||||
event.mask = get_modifiers();
|
||||
|
||||
event.data.mouse.button = button;
|
||||
event.data.mouse.clicks = click_count;
|
||||
event.data.mouse.x = mshook->pt.x;
|
||||
event.data.mouse.y = mshook->pt.y;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Button %u clicked %u time(s). (%u, %u)\n",
|
||||
__FUNCTION__, __LINE__, event.data.mouse.button, event.data.mouse.clicks,
|
||||
event.data.mouse.x, event.data.mouse.y);
|
||||
|
||||
// Fire mouse clicked event.
|
||||
dispatch_event(&event);
|
||||
}
|
||||
|
||||
// Reset the number of clicks.
|
||||
if (button == click_button && (long int) (event.time - click_time) > hook_get_multi_click_time()) {
|
||||
// Reset the click count.
|
||||
click_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void process_mouse_moved(MSLLHOOKSTRUCT *mshook) {
|
||||
uint64_t timestamp = GetMessageTime();
|
||||
|
||||
// We received a mouse move event with the mouse actually moving.
|
||||
// This verifies that the mouse was moved after being depressed.
|
||||
if (last_click.x != mshook->pt.x || last_click.y != mshook->pt.y) {
|
||||
// Reset the click count.
|
||||
if (click_count != 0 && (long) (timestamp - click_time) > hook_get_multi_click_time()) {
|
||||
click_count = 0;
|
||||
}
|
||||
|
||||
// Populate mouse move event.
|
||||
event.time = timestamp;
|
||||
event.reserved = 0x00;
|
||||
|
||||
event.mask = get_modifiers();
|
||||
|
||||
// Check the modifier mask range for MASK_BUTTON1 - 5.
|
||||
bool mouse_dragged = event.mask & (MASK_BUTTON1 | MASK_BUTTON2 | MASK_BUTTON3 | MASK_BUTTON4 | MASK_BUTTON5);
|
||||
if (mouse_dragged) {
|
||||
// Create Mouse Dragged event.
|
||||
event.type = EVENT_MOUSE_DRAGGED;
|
||||
}
|
||||
else {
|
||||
// Create a Mouse Moved event.
|
||||
event.type = EVENT_MOUSE_MOVED;
|
||||
}
|
||||
|
||||
event.data.mouse.button = MOUSE_NOBUTTON;
|
||||
event.data.mouse.clicks = click_count;
|
||||
event.data.mouse.x = mshook->pt.x;
|
||||
event.data.mouse.y = mshook->pt.y;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Mouse %s to %u, %u.\n",
|
||||
__FUNCTION__, __LINE__, mouse_dragged ? "dragged" : "moved",
|
||||
event.data.mouse.x, event.data.mouse.y);
|
||||
|
||||
// Fire mouse move event.
|
||||
dispatch_event(&event);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_mouse_wheel(MSLLHOOKSTRUCT *mshook, uint8_t direction) {
|
||||
// Track the number of clicks.
|
||||
// Reset the click count and previous button.
|
||||
click_count = 1;
|
||||
click_button = MOUSE_NOBUTTON;
|
||||
|
||||
// Populate mouse wheel event.
|
||||
event.time = GetMessageTime();
|
||||
event.reserved = 0x00;
|
||||
|
||||
event.type = EVENT_MOUSE_WHEEL;
|
||||
event.mask = get_modifiers();
|
||||
|
||||
event.data.wheel.clicks = click_count;
|
||||
event.data.wheel.x = mshook->pt.x;
|
||||
event.data.wheel.y = mshook->pt.y;
|
||||
|
||||
event.data.wheel.type = get_scroll_wheel_type();
|
||||
event.data.wheel.amount = get_scroll_wheel_amount();
|
||||
|
||||
/* Delta HIWORD(mshook->mouseData)
|
||||
* A positive value indicates that the wheel was rotated
|
||||
* forward, away from the user; a negative value indicates that
|
||||
* the wheel was rotated backward, toward the user. One wheel
|
||||
* click is defined as WHEEL_DELTA, which is 120. */
|
||||
event.data.wheel.rotation = ((int16_t) HIWORD(mshook->mouseData) / WHEEL_DELTA) * -1;
|
||||
|
||||
// Set the direction based on what event was received.
|
||||
event.data.wheel.direction = direction;
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Mouse wheel type %u, rotated %i units in the %u direction at %u, %u.\n",
|
||||
__FUNCTION__, __LINE__, event.data.wheel.type,
|
||||
event.data.wheel.amount * event.data.wheel.rotation,
|
||||
event.data.wheel.direction,
|
||||
event.data.wheel.x, event.data.wheel.y);
|
||||
|
||||
// Fire mouse wheel event.
|
||||
dispatch_event(&event);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK mouse_hook_event_proc(int nCode, WPARAM wParam, LPARAM lParam) {
|
||||
MSLLHOOKSTRUCT *mshook = (MSLLHOOKSTRUCT *) lParam;
|
||||
switch (wParam) {
|
||||
case WM_LBUTTONDOWN:
|
||||
set_modifier_mask(MASK_BUTTON1);
|
||||
process_button_pressed(mshook, MOUSE_BUTTON1);
|
||||
break;
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
set_modifier_mask(MASK_BUTTON2);
|
||||
process_button_pressed(mshook, MOUSE_BUTTON2);
|
||||
break;
|
||||
|
||||
case WM_MBUTTONDOWN:
|
||||
set_modifier_mask(MASK_BUTTON3);
|
||||
process_button_pressed(mshook, MOUSE_BUTTON3);
|
||||
break;
|
||||
|
||||
case WM_XBUTTONDOWN:
|
||||
case WM_NCXBUTTONDOWN:
|
||||
if (HIWORD(mshook->mouseData) == XBUTTON1) {
|
||||
set_modifier_mask(MASK_BUTTON4);
|
||||
process_button_pressed(mshook, MOUSE_BUTTON4);
|
||||
}
|
||||
else if (HIWORD(mshook->mouseData) == XBUTTON2) {
|
||||
set_modifier_mask(MASK_BUTTON5);
|
||||
process_button_pressed(mshook, MOUSE_BUTTON5);
|
||||
}
|
||||
else {
|
||||
// Extra mouse buttons.
|
||||
uint16_t button = HIWORD(mshook->mouseData);
|
||||
|
||||
// Add support for mouse 4 & 5.
|
||||
if (button == 4) {
|
||||
set_modifier_mask(MOUSE_BUTTON4);
|
||||
}
|
||||
else if (button == 5) {
|
||||
set_modifier_mask(MOUSE_BUTTON5);
|
||||
}
|
||||
|
||||
process_button_pressed(mshook, button);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
unset_modifier_mask(MASK_BUTTON1);
|
||||
process_button_released(mshook, MOUSE_BUTTON1);
|
||||
break;
|
||||
|
||||
case WM_RBUTTONUP:
|
||||
unset_modifier_mask(MASK_BUTTON2);
|
||||
process_button_released(mshook, MOUSE_BUTTON2);
|
||||
break;
|
||||
|
||||
case WM_MBUTTONUP:
|
||||
unset_modifier_mask(MASK_BUTTON3);
|
||||
process_button_released(mshook, MOUSE_BUTTON3);
|
||||
break;
|
||||
|
||||
case WM_XBUTTONUP:
|
||||
case WM_NCXBUTTONUP:
|
||||
if (HIWORD(mshook->mouseData) == XBUTTON1) {
|
||||
unset_modifier_mask(MASK_BUTTON4);
|
||||
process_button_released(mshook, MOUSE_BUTTON4);
|
||||
}
|
||||
else if (HIWORD(mshook->mouseData) == XBUTTON2) {
|
||||
unset_modifier_mask(MASK_BUTTON5);
|
||||
process_button_released(mshook, MOUSE_BUTTON5);
|
||||
}
|
||||
else {
|
||||
// Extra mouse buttons.
|
||||
uint16_t button = HIWORD(mshook->mouseData);
|
||||
|
||||
// Add support for mouse 4 & 5.
|
||||
if (button == 4) {
|
||||
unset_modifier_mask(MOUSE_BUTTON4);
|
||||
}
|
||||
else if (button == 5) {
|
||||
unset_modifier_mask(MOUSE_BUTTON5);
|
||||
}
|
||||
|
||||
process_button_released(mshook, MOUSE_BUTTON5);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
process_mouse_moved(mshook);
|
||||
break;
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
process_mouse_wheel(mshook, WHEEL_VERTICAL_DIRECTION);
|
||||
break;
|
||||
|
||||
/* For horizontal scroll wheel support.
|
||||
* NOTE Windows >= Vista
|
||||
* case 0x020E:
|
||||
*/
|
||||
case WM_MOUSEHWHEEL:
|
||||
process_mouse_wheel(mshook, WHEEL_HORIZONTAL_DIRECTION);
|
||||
break;
|
||||
|
||||
default:
|
||||
// In theory this *should* never execute.
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Unhandled Windows mouse event: %#X.\n",
|
||||
__FUNCTION__, __LINE__, (unsigned int) wParam);
|
||||
break;
|
||||
}
|
||||
|
||||
LRESULT hook_result = -1;
|
||||
if (nCode < 0 || event.reserved ^ 0x01) {
|
||||
hook_result = CallNextHookEx(mouse_event_hhook, nCode, wParam, lParam);
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Consuming the current event. (%li)\n",
|
||||
__FUNCTION__, __LINE__, (long) hook_result);
|
||||
}
|
||||
|
||||
return hook_result;
|
||||
}
|
||||
|
||||
|
||||
// Callback function that handles events.
|
||||
void CALLBACK win_hook_event_proc(HWINEVENTHOOK hook, DWORD event, HWND hWnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) {
|
||||
switch (event) {
|
||||
case EVENT_OBJECT_NAMECHANGE:
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Restarting Windows input hook on window event: %#X.\n",
|
||||
__FUNCTION__, __LINE__, event);
|
||||
|
||||
// Remove any keyboard or mouse hooks that are still running.
|
||||
if (keyboard_event_hhook != NULL) {
|
||||
UnhookWindowsHookEx(keyboard_event_hhook);
|
||||
}
|
||||
|
||||
if (mouse_event_hhook != NULL) {
|
||||
UnhookWindowsHookEx(mouse_event_hhook);
|
||||
}
|
||||
|
||||
// Restart the event hooks.
|
||||
keyboard_event_hhook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook_event_proc, hInst, 0);
|
||||
mouse_event_hhook = SetWindowsHookEx(WH_MOUSE_LL, mouse_hook_event_proc, hInst, 0);
|
||||
|
||||
// Re-initialize modifier masks.
|
||||
initialize_modifiers();
|
||||
|
||||
// FIXME We should compare the modifier mask before and after the restart
|
||||
// to determine if we should synthesize missing events.
|
||||
|
||||
// Check for event hook error.
|
||||
if (keyboard_event_hhook == NULL || mouse_event_hhook == NULL) {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: SetWindowsHookEx() failed! (%#lX)\n",
|
||||
__FUNCTION__, __LINE__, (unsigned long) GetLastError());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Unhandled Windows window event: %#X.\n",
|
||||
__FUNCTION__, __LINE__, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IOHOOK_API int hook_run() {
|
||||
int status = IOHOOK_FAILURE;
|
||||
|
||||
// Set the thread id we want to signal later.
|
||||
hook_thread_id = GetCurrentThreadId();
|
||||
|
||||
// Spot check the hInst incase the library was statically linked and DllMain
|
||||
// did not receive a pointer on load.
|
||||
if (hInst == NULL) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: hInst was not set by DllMain().\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
|
||||
hInst = GetModuleHandle(NULL);
|
||||
if (hInst != NULL) {
|
||||
// Initialize native input helper functions.
|
||||
load_input_helper();
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: Could not determine hInst for SetWindowsHookEx()! (%#lX)\n",
|
||||
__FUNCTION__, __LINE__, (unsigned long) GetLastError());
|
||||
|
||||
status = IOHOOK_ERROR_GET_MODULE_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the native hooks.
|
||||
keyboard_event_hhook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook_event_proc, hInst, 0);
|
||||
mouse_event_hhook = SetWindowsHookEx(WH_MOUSE_LL, mouse_hook_event_proc, hInst, 0);
|
||||
|
||||
// Create a window event hook to listen for capture change.
|
||||
win_event_hhook = SetWinEventHook(
|
||||
EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_NAMECHANGE,
|
||||
NULL,
|
||||
win_hook_event_proc,
|
||||
0, 0,
|
||||
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
|
||||
|
||||
// If we did not encounter a problem, start processing events.
|
||||
if (keyboard_event_hhook != NULL && mouse_event_hhook != NULL) {
|
||||
if (win_event_hhook == NULL) {
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: SetWinEventHook() failed!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: SetWindowsHookEx() successful.\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
|
||||
// Check and setup modifiers.
|
||||
initialize_modifiers();
|
||||
|
||||
// Set the exit status.
|
||||
status = IOHOOK_SUCCESS;
|
||||
|
||||
// Windows does not have a hook start event or callback so we need to
|
||||
// manually fake it.
|
||||
hook_start_proc();
|
||||
|
||||
// Block until the thread receives an WM_QUIT request.
|
||||
MSG message;
|
||||
while (GetMessage(&message, (HWND) NULL, 0, 0) > 0) {
|
||||
TranslateMessage(&message);
|
||||
DispatchMessage(&message);
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: SetWindowsHookEx() failed! (%#lX)\n",
|
||||
__FUNCTION__, __LINE__, (unsigned long) GetLastError());
|
||||
|
||||
status = IOHOOK_ERROR_SET_WINDOWS_HOOK_EX;
|
||||
}
|
||||
|
||||
|
||||
// Unregister any hooks that may still be installed.
|
||||
unregister_running_hooks();
|
||||
|
||||
// We must explicitly call the cleanup handler because Windows does not
|
||||
// provide a thread cleanup method like POSIX pthread_cleanup_push/pop.
|
||||
hook_stop_proc();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
IOHOOK_API int hook_stop() {
|
||||
int status = IOHOOK_FAILURE;
|
||||
|
||||
// Try to exit the thread naturally.
|
||||
if (PostThreadMessage(hook_thread_id, WM_QUIT, (WPARAM) NULL, (LPARAM) NULL)) {
|
||||
status = IOHOOK_SUCCESS;
|
||||
}
|
||||
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Status: %#X.\n",
|
||||
__FUNCTION__, __LINE__, status);
|
||||
|
||||
return status;
|
||||
}
|
104
vendor/github.com/robotn/gohook/hook/windows/input.h
generated
vendored
Normal file
104
vendor/github.com/robotn/gohook/hook/windows/input.h
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
/***********************************************************************
|
||||
Input
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef _included_input_helper
|
||||
#define _included_input_helper
|
||||
|
||||
#include <limits.h>
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef LPFN_ISWOW64PROCESS
|
||||
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
|
||||
#endif
|
||||
|
||||
typedef void* (CALLBACK *KbdLayerDescriptor) (VOID);
|
||||
|
||||
#define CAPLOK 0x01
|
||||
#define WCH_NONE 0xF000
|
||||
#define WCH_DEAD 0xF001
|
||||
|
||||
#ifndef WM_MOUSEHWHEEL
|
||||
#define WM_MOUSEHWHEEL 0x020E
|
||||
#endif
|
||||
|
||||
typedef struct _VK_TO_WCHARS {
|
||||
BYTE VirtualKey;
|
||||
BYTE Attributes;
|
||||
WCHAR wch[];
|
||||
} VK_TO_WCHARS, *PVK_TO_WCHARS;
|
||||
|
||||
typedef struct _LIGATURE {
|
||||
BYTE VirtualKey;
|
||||
WORD ModificationNumber;
|
||||
WCHAR wch[];
|
||||
} LIGATURE, *PLIGATURE;
|
||||
|
||||
typedef struct _VK_TO_BIT {
|
||||
BYTE Vk;
|
||||
BYTE ModBits;
|
||||
} VK_TO_BIT, *PVK_TO_BIT;
|
||||
|
||||
typedef struct _MODIFIERS {
|
||||
PVK_TO_BIT pVkToBit; // __ptr64
|
||||
WORD wMaxModBits;
|
||||
BYTE ModNumber[];
|
||||
} MODIFIERS, *PMODIFIERS;
|
||||
|
||||
typedef struct _VSC_VK {
|
||||
BYTE Vsc;
|
||||
USHORT Vk;
|
||||
} VSC_VK, *PVSC_VK;
|
||||
|
||||
typedef struct _VK_TO_WCHAR_TABLE {
|
||||
PVK_TO_WCHARS pVkToWchars; // __ptr64
|
||||
BYTE nModifications;
|
||||
BYTE cbSize;
|
||||
} VK_TO_WCHAR_TABLE, *PVK_TO_WCHAR_TABLE;
|
||||
|
||||
typedef struct _DEADKEY {
|
||||
DWORD dwBoth;
|
||||
WCHAR wchComposed;
|
||||
USHORT uFlags;
|
||||
} DEADKEY, *PDEADKEY;
|
||||
|
||||
typedef struct _VSC_LPWSTR {
|
||||
BYTE vsc;
|
||||
WCHAR *pwsz; // __ptr64
|
||||
} VSC_LPWSTR, *PVSC_LPWSTR;
|
||||
|
||||
typedef struct tagKbdLayer {
|
||||
PMODIFIERS pCharModifiers; // __ptr64
|
||||
PVK_TO_WCHAR_TABLE pVkToWcharTable; // __ptr64
|
||||
PDEADKEY pDeadKey; // __ptr64
|
||||
PVSC_LPWSTR pKeyNames; // __ptr64
|
||||
PVSC_LPWSTR pKeyNamesExt; // __ptr64
|
||||
WCHAR **pKeyNamesDead; // __ptr64
|
||||
USHORT *pusVSCtoVK; // __ptr64
|
||||
BYTE bMaxVSCtoVK;
|
||||
PVSC_VK pVSCtoVK_E0; // __ptr64
|
||||
PVSC_VK pVSCtoVK_E1; // __ptr64
|
||||
DWORD fLocaleFlags;
|
||||
BYTE nLgMax;
|
||||
BYTE cbLgEntry;
|
||||
PLIGATURE pLigature; // __ptr64
|
||||
DWORD dwType;
|
||||
DWORD dwSubType;
|
||||
} KBDTABLES, *PKBDTABLES; // __ptr64
|
||||
|
||||
|
||||
extern SIZE_T keycode_to_unicode(DWORD keycode, PWCHAR buffer, SIZE_T size);
|
||||
|
||||
//extern DWORD unicode_to_keycode(wchar_t unicode);
|
||||
|
||||
extern unsigned short keycode_to_scancode(DWORD vk_code, DWORD flags);
|
||||
|
||||
extern DWORD scancode_to_keycode(unsigned short scancode);
|
||||
|
||||
// Initialize the locale list and wow64 pointer size.
|
||||
extern int load_input_helper();
|
||||
|
||||
// Cleanup the initialized locales.
|
||||
extern int unload_input_helper();
|
||||
|
||||
#endif
|
832
vendor/github.com/robotn/gohook/hook/windows/input_c.h
generated
vendored
Normal file
832
vendor/github.com/robotn/gohook/hook/windows/input_c.h
generated
vendored
Normal file
@ -0,0 +1,832 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "../iohook.h"
|
||||
#include "../logger_c.h"
|
||||
#include "input.h"
|
||||
|
||||
static const uint16_t keycode_scancode_table[][2] = {
|
||||
/* idx { vk_code, scancode }, */
|
||||
/* 0 */ { VC_UNDEFINED, 0x0000 }, // 0x00
|
||||
/* 1 */ { MOUSE_BUTTON1, VK_ESCAPE }, // 0x01
|
||||
/* 2 */ { MOUSE_BUTTON2, 0x0031 }, // 0x02
|
||||
/* 3 */ { VC_UNDEFINED, 0x0032 }, // 0x03 VK_CANCEL
|
||||
/* 4 */ { MOUSE_BUTTON3, 0x0033 }, // 0x04
|
||||
/* 5 */ { MOUSE_BUTTON4, 0x0034 }, // 0x05
|
||||
/* 6 */ { MOUSE_BUTTON5, 0x0035 }, // 0x06
|
||||
/* 7 */ { VC_UNDEFINED, 0x0036 }, // 0x07 Undefined
|
||||
/* 8 */ { VC_BACKSPACE, 0x0037 }, // 0x08 VK_BACK
|
||||
/* 9 */ { VC_TAB, 0x0038 }, // 0x09 VK_TAB
|
||||
/* 10 */ { VC_UNDEFINED, 0x0039 }, // 0x0A Reserved
|
||||
/* 11 */ { VC_UNDEFINED, 0x0030 }, // 0x0B Reserved
|
||||
/* 12 */ { VC_CLEAR, VK_OEM_MINUS }, // 0x0C VK_CLEAR
|
||||
/* 13 */ { VC_ENTER, VK_OEM_PLUS }, // 0x0D VK_RETURN
|
||||
/* 14 */ { VC_UNDEFINED, VK_BACK }, // 0x0E Undefined
|
||||
/* 15 */ { VC_UNDEFINED, VK_TAB }, // 0x0F Undefined
|
||||
/* 16 */ { VC_SHIFT_L, 0x0051 }, // 0x10 VK_SHIFT
|
||||
/* 17 */ { VC_CONTROL_L, 0x0057 }, // 0x11 VK_CONTROL
|
||||
/* 18 */ { VC_ALT_L, 0x0045 }, // 0x12 VK_MENU ALT key
|
||||
/* 19 */ { VC_PAUSE, 0x0052 }, // 0x13 VK_PAUSE
|
||||
/* 20 */ { VC_CAPS_LOCK, 0x0054 }, // 0x14 VK_CAPITAL CAPS LOCK key
|
||||
/* 21 */ { VC_KATAKANA, 0x0059 }, // 0x15 VK_KANA IME Kana mode
|
||||
/* 22 */ { VC_UNDEFINED, 0x0055 }, // 0x16 Undefined
|
||||
/* 23 */ { VC_UNDEFINED, 0x0049 }, // 0x17 VK_JUNJA IME Junja mode
|
||||
/* 24 */ { VC_UNDEFINED, 0x004F }, // 0x18 VK_FINAL
|
||||
/* 25 */ { VC_KANJI, 0x0050 }, // 0x19 VK_KANJI / VK_HANJA IME Kanji / Hanja mode
|
||||
/* 26 */ { VC_UNDEFINED, 0x00DB }, // 0x1A Undefined
|
||||
/* 27 */ { VC_ESCAPE, 0x00DD }, // 0x1B VK_ESCAPE ESC key
|
||||
/* 28 */ { VC_UNDEFINED, VK_RETURN }, // 0x1C VK_CONVERT IME convert// 0x1C
|
||||
/* 29 */ { VC_UNDEFINED, VK_LCONTROL }, // 0x1D VK_NONCONVERT IME nonconvert
|
||||
/* 30 */ { VC_UNDEFINED, 0x0041 }, // 0x1E VK_ACCEPT IME accept
|
||||
/* 31 */ { VC_UNDEFINED, 0x0053 }, // 0x1F VK_MODECHANGE IME mode change request
|
||||
/* 32 */ { VC_SPACE, 0x0044 }, // 0x20 VK_SPACE SPACEBAR
|
||||
/* 33 */ { VC_PAGE_UP, 0x0046 }, // 0x21 VK_PRIOR PAGE UP key
|
||||
/* 34 */ { VC_PAGE_DOWN, 0x0047 }, // 0x22 VK_NEXT PAGE DOWN key
|
||||
/* 35 */ { VC_END, 0x0048 }, // 0x23 VK_END END key
|
||||
/* 36 */ { VC_HOME, 0x004A }, // 0x24 VK_HOME HOME key
|
||||
/* 37 */ { VC_LEFT, 0x004B }, // 0x25 VK_LEFT LEFT ARROW key
|
||||
/* 38 */ { VC_UP, 0x004C }, // 0x26 VK_UP UP ARROW key
|
||||
/* 39 */ { VC_RIGHT, VK_OEM_1 }, // 0x27 VK_RIGHT RIGHT ARROW key
|
||||
/* 40 */ { VC_DOWN, VK_OEM_7 }, // 0x28 VK_DOWN DOWN ARROW key
|
||||
/* 41 */ { VC_UNDEFINED, VK_OEM_3 }, // 0x29 VK_SELECT SELECT key
|
||||
/* 42 */ { VC_UNDEFINED, VK_LSHIFT }, // 0x2A VK_PRINT PRINT key
|
||||
/* 43 */ { VC_UNDEFINED, VK_OEM_5 }, // 0x2B VK_EXECUTE EXECUTE key
|
||||
/* 44 */ { VC_PRINTSCREEN, 0x005A }, // 0x2C VK_SNAPSHOT PRINT SCREEN key
|
||||
/* 45 */ { VC_INSERT, 0x0058 }, // 0x2D VK_INSERT INS key
|
||||
/* 46 */ { VC_DELETE, 0x0043 }, // 0x2E VK_DELETE DEL key
|
||||
/* 47 */ { VC_UNDEFINED, 0x0056 }, // 0x2F VK_HELP HELP key
|
||||
/* 48 */ { VC_0, 0x0042 }, // 0x30 0 key
|
||||
/* 49 */ { VC_1, 0x004E }, // 0x31 1 key
|
||||
/* 50 */ { VC_2, 0x004D }, // 0x32 2 key
|
||||
/* 51 */ { VC_3, VK_OEM_COMMA }, // 0x33 3 key
|
||||
/* 52 */ { VC_4, VK_OEM_PERIOD }, // 0x34 4 key
|
||||
/* 53 */ { VC_5, VK_OEM_2 }, // 0x35 5 key
|
||||
/* 54 */ { VC_6, VK_RSHIFT }, // 0x36 6 key
|
||||
/* 55 */ { VC_7, VK_MULTIPLY }, // 0x37 7 key
|
||||
/* 56 */ { VC_8, VK_LMENU }, // 0x38 8 key
|
||||
/* 57 */ { VC_9, VK_SPACE }, // 0x39 9 key
|
||||
/* 58 */ { VC_UNDEFINED, VK_CAPITAL }, // 0x3A Undefined
|
||||
/* 59 */ { VC_UNDEFINED, VK_F1 }, // 0x3B Undefined
|
||||
/* 60 */ { VC_UNDEFINED, VK_F2 }, // 0x3C Undefined
|
||||
/* 61 */ { VC_UNDEFINED, VK_F3 }, // 0x3D Undefined
|
||||
/* 62 */ { VC_UNDEFINED, VK_F4 }, // 0x3E Undefined
|
||||
/* 63 */ { VC_UNDEFINED, VK_F5 }, // 0x3F Undefined
|
||||
/* 64 */ { VC_UNDEFINED, VK_F6 }, // 0x40 Undefined
|
||||
/* 65 */ { VC_A, VK_F7 }, // 0x41 A key
|
||||
/* 66 */ { VC_B, VK_F8 }, // 0x42 B key
|
||||
/* 67 */ { VC_C, VK_F9 }, // 0x43 C key
|
||||
/* 68 */ { VC_D, VK_F10 }, // 0x44 D key
|
||||
/* 69 */ { VC_E, VK_NUMLOCK }, // 0x45 E key
|
||||
/* 70 */ { VC_F, VK_SCROLL }, // 0x46 F key
|
||||
/* 71 */ { VC_G, VK_NUMPAD7 }, // 0x47 G key
|
||||
/* 72 */ { VC_H, VK_NUMPAD8 }, // 0x48 H key
|
||||
/* 73 */ { VC_I, VK_NUMPAD9 }, // 0x49 I key
|
||||
/* 74 */ { VC_J, VK_SUBTRACT }, // 0x4A J key
|
||||
/* 75 */ { VC_K, VK_NUMPAD4 }, // 0x4B K key
|
||||
/* 76 */ { VC_L, VK_NUMPAD5 }, // 0x4C L key
|
||||
/* 77 */ { VC_M, VK_NUMPAD6 }, // 0x4D M key
|
||||
/* 78 */ { VC_N, VK_ADD }, // 0x4E N key
|
||||
/* 79 */ { VC_O, VK_NUMPAD1 }, // 0x4F O key
|
||||
/* 80 */ { VC_P, VK_NUMPAD2 }, // 0x50 P key
|
||||
/* 81 */ { VC_Q, VK_NUMPAD3 }, // 0x51 Q key
|
||||
/* 82 */ { VC_R, VK_NUMPAD0 }, // 0x52 R key
|
||||
/* 83 */ { VC_S, VK_DECIMAL }, // 0x53 S key
|
||||
/* 84 */ { VC_T, 0x0000 }, // 0x54 T key
|
||||
/* 85 */ { VC_U, 0x0000 }, // 0x55 U key
|
||||
/* 86 */ { VC_V, 0x0000 }, // 0x56 V key
|
||||
/* 87 */ { VC_W, VK_F11 }, // 0x57 W key
|
||||
/* 88 */ { VC_X, VK_F12 }, // 0x58 X key
|
||||
/* 89 */ { VC_Y, 0x0000 }, // 0x59 Y key
|
||||
/* 90 */ { VC_Z, 0x0000 }, // 0x5A Z key
|
||||
/* 91 */ { VC_META_L, VK_F13 }, // 0x5B VK_LWIN Left Windows key (Natural keyboard)
|
||||
/* 92 */ { VC_META_R, VK_F14 }, // 0x5C VK_RWIN Right Windows key (Natural keyboard)
|
||||
/* 93 */ { VC_CONTEXT_MENU, VK_F15 }, // 0x5D VK_APPS Applications key (Natural keyboard)
|
||||
/* 94 */ { VC_UNDEFINED, 0x0000 }, // 0x5E Reserved
|
||||
/* 95 */ { VC_SLEEP, 0x0000 }, // 0x5F VK_SLEEP Computer Sleep key
|
||||
/* 96 */ { VC_KP_0, 0x0000 }, // 0x60 VK_NUMPAD0 Numeric keypad 0 key
|
||||
/* 97 */ { VC_KP_1, 0x0000 }, // 0x61 VK_NUMPAD1 Numeric keypad 1 key
|
||||
/* 98 */ { VC_KP_2, 0x0000 }, // 0x62 VK_NUMPAD2 Numeric keypad 2 key
|
||||
/* 99 */ { VC_KP_3, VK_F16 }, // 0x63 VK_NUMPAD3 Numeric keypad 3 key
|
||||
/* 100 */ { VC_KP_4, VK_F17 }, // 0x64 VK_NUMPAD4 Numeric keypad 4 key
|
||||
/* 101 */ { VC_KP_5, VK_F18 }, // 0x65 VK_NUMPAD5 Numeric keypad 5 key
|
||||
/* 102 */ { VC_KP_6, VK_F19 }, // 0x66 VK_NUMPAD6 Numeric keypad 6 key
|
||||
/* 103 */ { VC_KP_7, VK_F20 }, // 0x67 VK_NUMPAD7 Numeric keypad 7 key
|
||||
/* 104 */ { VC_KP_8, VK_F21 }, // 0x68 VK_NUMPAD8 Numeric keypad 8 key
|
||||
/* 105 */ { VC_KP_9, VK_F22 }, // 0x69 VK_NUMPAD9 Numeric keypad 9 key
|
||||
/* 106 */ { VC_KP_MULTIPLY, VK_F23 }, // 0x6A VK_MULTIPLY Multiply key
|
||||
/* 107 */ { VC_KP_ADD, VK_F24 }, // 0x6B VK_ADD Add key
|
||||
/* 108 */ { VC_UNDEFINED, 0x0000 }, // 0x6C VK_SEPARATOR Separator key
|
||||
/* 109 */ { VC_KP_SUBTRACT, 0x0000 }, // 0x6D VK_SUBTRACT Subtract key
|
||||
/* 110 */ { VC_KP_SEPARATOR, 0x0000 }, // 0x6E VK_DECIMAL Decimal key
|
||||
/* 111 */ { VC_KP_DIVIDE, 0x0000 }, // 0x6F VK_DIVIDE Divide key
|
||||
/* 112 */ { VC_F1, VK_KANA }, // 0x70 VK_F1 F1 key
|
||||
/* 113 */ { VC_F2, 0x0000 }, // 0x71 VK_F2 F2 key
|
||||
/* 114 */ { VC_F3, 0x0000 }, // 0x72 VK_F3 F3 key
|
||||
/* 115 */ { VC_F4, 0x0000 }, // 0x73 VK_F4 F4 key
|
||||
/* 116 */ { VC_F5, 0x0000 }, // 0x74 VK_F5 F5 key
|
||||
/* 117 */ { VC_F6, 0x0000 }, // 0x75 VK_F6 F6 key
|
||||
/* 118 */ { VC_F7, 0x0000 }, // 0x76 VK_F7 F7 key
|
||||
/* 119 */ { VC_F8, 0x0000 }, // 0x77 VK_F8 F8 key
|
||||
/* 120 */ { VC_F9, 0x0000 }, // 0x78 VK_F9 F9 key
|
||||
/* 121 */ { VC_F10, VK_KANJI }, // 0x79 VK_F10 F10 key
|
||||
/* 122 */ { VC_F11, 0x0000 }, // 0x7A VK_F11 F11 key
|
||||
/* 123 */ { VC_F12, 0x0000 }, // 0x7B VK_F12 F12 key
|
||||
/* 124 */ { VC_F13, 0x0000 }, // 0x7C VK_F13 F13 key
|
||||
/* 125 */ { VC_F14, VK_OEM_8 }, // 0x7D VK_F14 F14 key
|
||||
/* 126 */ { VC_F15, 0x0000 }, // 0x7E VK_F15 F15 key
|
||||
/* 127 */ { VC_F16, 0x0000 }, // 0x7F VK_F16 F16 key
|
||||
|
||||
// No Offset Offset (i & 0x007F) | 0x80
|
||||
|
||||
/* 128 */ { VC_F17, 0x0000 }, // 0x80 VK_F17 F17 key
|
||||
/* 129 */ { VC_F18, 0x0000 }, // 0x81 VK_F18 F18 key
|
||||
/* 130 */ { VC_F19, 0x0000 }, // 0x82 VK_F19 F19 key
|
||||
/* 131 */ { VC_F20, 0x0000 }, // 0x83 VK_F20 F20 key
|
||||
/* 132 */ { VC_F21, 0x0000 }, // 0x84 VK_F21 F21 key
|
||||
/* 133 */ { VC_F22, 0x0000 }, // 0x85 VK_F22 F22 key
|
||||
/* 134 */ { VC_F23, 0x0000 }, // 0x86 VK_F23 F23 key
|
||||
/* 135 */ { VC_F24, 0x0000 }, // 0x87 VK_F24 F24 key
|
||||
/* 136 */ { VC_UNDEFINED, 0x0000 }, // 0x88 Unassigned
|
||||
/* 137 */ { VC_UNDEFINED, 0x0000 }, // 0x89 Unassigned
|
||||
/* 138 */ { VC_UNDEFINED, 0x0000 }, // 0x8A Unassigned
|
||||
/* 139 */ { VC_UNDEFINED, 0x0000 }, // 0x8B Unassigned
|
||||
/* 140 */ { VC_UNDEFINED, 0x0000 }, // 0x8C Unassigned
|
||||
/* 141 */ { VC_UNDEFINED, 0x0000 }, // 0x8D Unassigned
|
||||
/* 142 */ { VC_UNDEFINED, 0x0000 }, // 0x8E Unassigned
|
||||
/* 143 */ { VC_UNDEFINED, 0x0000 }, // 0x8F Unassigned
|
||||
/* 144 */ { VC_NUM_LOCK, VK_MEDIA_PREV_TRACK }, // 0x90 VK_NUMLOCK NUM LOCK key
|
||||
/* 145 */ { VC_SCROLL_LOCK, 0x0000 }, // 0x91 VK_SCROLL SCROLL LOCK key
|
||||
/* 146 */ { VC_UNDEFINED, 0x0000 }, // 0x92 OEM specific
|
||||
/* 147 */ { VC_UNDEFINED, 0x0000 }, // 0x93 OEM specific
|
||||
/* 148 */ { VC_UNDEFINED, 0x0000 }, // 0x94 OEM specific
|
||||
/* 149 */ { VC_UNDEFINED, 0x0000 }, // 0x95 OEM specific
|
||||
/* 150 */ { VC_UNDEFINED, 0x0000 }, // 0x96 OEM specific
|
||||
/* 151 */ { VC_UNDEFINED, 0x0000 }, // 0x97 Unassigned
|
||||
/* 152 */ { VC_UNDEFINED, 0x0000 }, // 0x98 Unassigned
|
||||
/* 153 */ { VC_UNDEFINED, VK_MEDIA_NEXT_TRACK }, // 0x99 Unassigned
|
||||
/* 154 */ { VC_UNDEFINED, 0x0000 }, // 0x9A Unassigned
|
||||
/* 155 */ { VC_UNDEFINED, 0x0000 }, // 0x9B Unassigned
|
||||
/* 156 */ { VC_UNDEFINED, 0x0000 }, // 0x9C Unassigned
|
||||
/* 157 */ { VC_UNDEFINED, VK_RCONTROL }, // 0x9D Unassigned
|
||||
/* 158 */ { VC_UNDEFINED, 0x0000 }, // 0x9E Unassigned
|
||||
/* 159 */ { VC_UNDEFINED, 0x0000 }, // 0x9F Unassigned
|
||||
/* 160 */ { VC_SHIFT_L, VK_VOLUME_MUTE }, // 0xA0 VK_LSHIFT Left SHIFT key
|
||||
/* 161 */ { VC_SHIFT_R, VK_LAUNCH_APP2 }, // 0xA1 VK_RSHIFT Right SHIFT key
|
||||
/* 162 */ { VC_CONTROL_L, VK_MEDIA_PLAY_PAUSE }, // 0xA2 VK_LCONTROL Left CONTROL key
|
||||
/* 163 */ { VC_CONTROL_R, 0x0000 }, // 0xA3 VK_RCONTROL Right CONTROL key
|
||||
/* 164 */ { VC_ALT_L, VK_MEDIA_STOP }, // 0xA4 VK_LMENU Left MENU key
|
||||
/* 165 */ { VC_ALT_R, 0x0000 }, // 0xA5 VK_RMENU Right MENU key
|
||||
/* 166 */ { VC_BROWSER_BACK, 0x0000 }, // 0xA6 VK_BROWSER_BACK Browser Back key
|
||||
/* 167 */ { VC_BROWSER_FORWARD, 0x0000 }, // 0xA7 VK_BROWSER_FORWARD Browser Forward key
|
||||
/* 168 */ { VC_BROWSER_REFRESH, 0x0000 }, // 0xA8 VK_BROWSER_REFRESH Browser Refresh key
|
||||
/* 169 */ { VC_BROWSER_STOP, 0x0000 }, // 0xA9 VK_BROWSER_STOP Browser Stop key
|
||||
/* 170 */ { VC_BROWSER_SEARCH, 0x0000 }, // 0xAA VK_BROWSER_SEARCH Browser Search key
|
||||
/* 171 */ { VC_BROWSER_FAVORITES, 0x0000 }, // 0xAB VK_BROWSER_FAVORITES Browser Favorites key
|
||||
/* 172 */ { VC_BROWSER_HOME, 0x0000 }, // 0xAC VK_BROWSER_HOME Browser Start and Home key
|
||||
/* 173 */ { VC_VOLUME_MUTE, 0x0000 }, // 0xAD VK_VOLUME_MUTE Volume Mute key
|
||||
/* 174 */ { VC_VOLUME_DOWN, VK_VOLUME_DOWN }, // 0xAE VK_VOLUME_DOWN Volume Down key
|
||||
/* 175 */ { VC_VOLUME_UP, 0x0000 }, // 0xAF VK_VOLUME_UP Volume Up key
|
||||
/* 176 */ { VC_MEDIA_NEXT, VK_VOLUME_UP }, // 0xB0 VK_MEDIA_NEXT_TRACK Next Track key
|
||||
/* 177 */ { VC_MEDIA_PREVIOUS, 0x0000 }, // 0xB1 VK_MEDIA_PREV_TRACK Previous Track key
|
||||
/* 178 */ { VC_MEDIA_STOP, VK_BROWSER_HOME }, // 0xB2 VK_MEDIA_STOP Stop Media key
|
||||
/* 179 */ { VC_MEDIA_PLAY, 0x0000 }, // 0xB3 VK_MEDIA_PLAY_PAUSE Play/Pause Media key
|
||||
/* 180 */ { VC_UNDEFINED, 0x0000 }, // 0xB4 VK_LAUNCH_MAIL Start Mail key
|
||||
/* 181 */ { VC_MEDIA_SELECT, VK_DIVIDE }, // 0xB5 VK_LAUNCH_MEDIA_SELECT Select Media key
|
||||
/* 182 */ { VC_APP_MAIL, 0x0000 }, // 0xB6 VK_LAUNCH_APP1 Start Application 1 key
|
||||
/* 183 */ { VC_APP_CALCULATOR, VK_SNAPSHOT }, // 0xB7 VK_LAUNCH_APP2 Start Application 2 key
|
||||
/* 184 */ { VC_UNDEFINED, VK_RMENU }, // 0xB8 Reserved
|
||||
/* 185 */ { VC_UNDEFINED, 0x0000 }, // 0xB9 Reserved
|
||||
/* 186 */ { VC_SEMICOLON, 0x0000 }, // 0xBA VK_OEM_1 Varies by keyboard. For the US standard keyboard, the ';:' key
|
||||
/* 187 */ { VC_EQUALS, 0x0000 }, // 0xBB VK_OEM_PLUS For any country/region, the '+' key
|
||||
/* 188 */ { VC_COMMA, 0x00E6 }, // 0xBC VK_OEM_COMMA For any country/region, the ',' key
|
||||
/* 189 */ { VC_MINUS, 0x0000 }, // 0xBD VK_OEM_MINUS For any country/region, the '-' key
|
||||
/* 190 */ { VC_PERIOD, 0x0000 }, // 0xBE VK_OEM_PERIOD For any country/region, the '.' key
|
||||
/* 191 */ { VC_SLASH, 0x0000 }, // 0xBF VK_OEM_2 Varies by keyboard. For the US standard keyboard, the '/?' key
|
||||
/* 192 */ { VC_BACKQUOTE, 0x0000 }, // 0xC0 VK_OEM_3 Varies by keyboard. For the US standard keyboard, the '`~' key
|
||||
/* 193 */ { VC_UNDEFINED, 0x0000 }, // 0xC1 Reserved
|
||||
/* 194 */ { VC_UNDEFINED, 0x0000 }, // 0xC2 Reserved
|
||||
/* 195 */ { VC_UNDEFINED, 0x0000 }, // 0xC3 Reserved
|
||||
/* 196 */ { VC_UNDEFINED, 0x0000 }, // 0xC4 Reserved
|
||||
/* 197 */ { VC_UNDEFINED, VK_PAUSE }, // 0xC5 Reserved
|
||||
/* 198 */ { VC_UNDEFINED, 0x0000 }, // 0xC6 Reserved
|
||||
/* 199 */ { VC_UNDEFINED, VK_HOME }, // 0xC7 Reserved
|
||||
/* 200 */ { VC_UNDEFINED, VK_UP }, // 0xC8 Reserved
|
||||
/* 201 */ { VC_UNDEFINED, VK_PRIOR }, // 0xC9 Reserved
|
||||
/* 202 */ { VC_UNDEFINED, 0x0000 }, // 0xCA Reserved
|
||||
/* 203 */ { VC_UNDEFINED, VK_LEFT }, // 0xCB Reserved
|
||||
/* 204 */ { VC_UNDEFINED, VK_CLEAR }, // 0xCC Reserved
|
||||
/* 205 */ { VC_UNDEFINED, VK_RIGHT }, // 0xCD Reserved
|
||||
/* 206 */ { VC_UNDEFINED, 0x0000 }, // 0xCE Reserved
|
||||
/* 207 */ { VC_UNDEFINED, VK_END }, // 0xCF Reserved
|
||||
/* 208 */ { VC_UNDEFINED, VK_DOWN }, // 0xD0 Reserved
|
||||
/* 209 */ { VC_UNDEFINED, VK_NEXT }, // 0xD1 Reserved
|
||||
/* 210 */ { VC_UNDEFINED, VK_INSERT }, // 0xD2 Reserved
|
||||
/* 211 */ { VC_UNDEFINED, VK_DELETE }, // 0xD3 Reserved
|
||||
/* 212 */ { VC_UNDEFINED, 0x0000 }, // 0xD4 Reserved
|
||||
/* 213 */ { VC_UNDEFINED, 0x0000 }, // 0xD5 Reserved
|
||||
/* 214 */ { VC_UNDEFINED, 0x0000 }, // 0xD6 Reserved
|
||||
/* 215 */ { VC_UNDEFINED, 0x0000 }, // 0xD7 Reserved
|
||||
/* 216 */ { VC_UNDEFINED, 0x0000 }, // 0xD8 Unassigned
|
||||
/* 217 */ { VC_UNDEFINED, 0x0000 }, // 0xD9 Unassigned
|
||||
/* 218 */ { VC_UNDEFINED, 0x0000 }, // 0xDA Unassigned
|
||||
/* 219 */ { VC_OPEN_BRACKET, VK_LWIN }, // 0xDB VK_OEM_4 Varies by keyboard. For the US standard keyboard, the '[{' key
|
||||
/* 220 */ { VC_BACK_SLASH, VK_RWIN }, // 0xDC VK_OEM_5 Varies by keyboard. For the US standard keyboard, the '\|' key
|
||||
/* 221 */ { VC_CLOSE_BRACKET, VK_APPS }, // 0xDD VK_OEM_6 Varies by keyboard. For the US standard keyboard, the ']}' key
|
||||
/* 222 */ { VC_QUOTE, 0x0000 }, // 0xDE VK_OEM_7 Varies by keyboard. For the US standard keyboard, the 'single-quote/double-quote' key
|
||||
/* 223 */ { VC_YEN, VK_SLEEP }, // 0xDF VK_OEM_8 Varies by keyboard.
|
||||
/* 224 */ { VC_UNDEFINED, 0x0000 }, // 0xE0 Reserved
|
||||
/* 225 */ { VC_UNDEFINED, 0x0000 }, // 0xE1 OEM specific
|
||||
/* 226 */ { VC_UNDEFINED, 0x0000 }, // 0xE2 VK_OEM_102 Either the angle bracket key or the backslash key on the RT 102-key keyboard
|
||||
/* 227 */ { VC_UNDEFINED, 0x0000 }, // 0xE3 OEM specific
|
||||
/* 228 */ { VC_UNDEFINED, 0x00E5 }, // 0xE4 VC_APP_PICTURES OEM specific
|
||||
/* 229 */ { VC_APP_PICTURES, VK_BROWSER_SEARCH }, // 0xE5 VK_PROCESSKEY IME PROCESS key
|
||||
/* 230 */ { VC_APP_MUSIC, VK_BROWSER_FAVORITES }, // 0xE6 OEM specific
|
||||
/* 231 */ { VC_UNDEFINED, VK_BROWSER_REFRESH }, // 0xE7 VK_PACKET Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods.
|
||||
/* 232 */ { VC_UNDEFINED, VK_BROWSER_STOP }, // 0xE8 Unassigned
|
||||
/* 233 */ { VC_UNDEFINED, VK_BROWSER_FORWARD }, // 0xE9 OEM specific
|
||||
/* 234 */ { VC_UNDEFINED, VK_BROWSER_BACK }, // 0xEA OEM specific
|
||||
/* 235 */ { VC_UNDEFINED, 0x0000 }, // 0xEB OEM specific
|
||||
/* 236 */ { VC_UNDEFINED, VK_LAUNCH_APP1 }, // 0xEC OEM specific
|
||||
/* 237 */ { VC_UNDEFINED, VK_LAUNCH_MEDIA_SELECT }, // 0xED OEM specific
|
||||
/* 238 */ { VC_UNDEFINED, 0x0000 }, // 0xEE OEM specific
|
||||
/* 239 */ { VC_UNDEFINED, 0x0000 }, // 0xEF OEM specific
|
||||
/* 240 */ { VC_UNDEFINED, 0x0000 }, // 0xF0 OEM specific
|
||||
/* 241 */ { VC_UNDEFINED, 0x0000 }, // 0xF1 OEM specific
|
||||
/* 242 */ { VC_UNDEFINED, 0x0000 }, // 0xF2 OEM specific
|
||||
/* 243 */ { VC_UNDEFINED, 0x0000 }, // 0xF3 OEM specific
|
||||
/* 244 */ { VC_UNDEFINED, 0x0000 }, // 0xF4 OEM specific
|
||||
/* 245 */ { VC_UNDEFINED, 0x0000 }, // 0xF5 OEM specific
|
||||
/* 246 */ { VC_UNDEFINED, 0x0000 }, // 0xF6 VK_ATTN Attn key
|
||||
/* 247 */ { VC_UNDEFINED, 0x0000 }, // 0xF7 VK_CRSEL CrSel key
|
||||
/* 248 */ { VC_UNDEFINED, 0x0000 }, // 0xF8 VK_EXSEL ExSel key
|
||||
/* 249 */ { VC_UNDEFINED, 0x0000 }, // 0xF9 VK_EREOF Erase EOF key
|
||||
/* 250 */ { VC_UNDEFINED, 0x0000 }, // 0xFA VK_PLAY Play key
|
||||
/* 251 */ { VC_UNDEFINED, 0x0000 }, // 0xFB VK_ZOOM Zoom key
|
||||
/* 252 */ { VC_UNDEFINED, 0x0000 }, // 0xFC VK_NONAME Reserved
|
||||
/* 253 */ { VC_UNDEFINED, 0x0000 }, // 0xFD
|
||||
/* 254 */ { VC_CLEAR, 0x0000 }, // 0xFE VK_OEM_CLEAR Clear key
|
||||
/* 255 */ { VC_UNDEFINED, 0x0000 } // 0xFE Unassigned
|
||||
};
|
||||
|
||||
unsigned short keycode_to_scancode(DWORD vk_code, DWORD flags) {
|
||||
unsigned short scancode = VC_UNDEFINED;
|
||||
|
||||
// Check the vk_code is in range.
|
||||
// NOTE vk_code >= 0 is assumed because DWORD is unsigned.
|
||||
if (vk_code < sizeof(keycode_scancode_table) / sizeof(keycode_scancode_table[0])) {
|
||||
scancode = keycode_scancode_table[vk_code][0];
|
||||
|
||||
if (flags & LLKHF_EXTENDED) {
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: EXTD2, vk_code %li\n",
|
||||
__FUNCTION__, __LINE__, vk_code);
|
||||
|
||||
switch (vk_code) {
|
||||
case VK_PRIOR:
|
||||
case VK_NEXT:
|
||||
case VK_END:
|
||||
case VK_HOME:
|
||||
case VK_LEFT:
|
||||
case VK_UP:
|
||||
case VK_RIGHT:
|
||||
case VK_DOWN:
|
||||
|
||||
case VK_INSERT:
|
||||
case VK_DELETE:
|
||||
scancode |= 0xEE00;
|
||||
break;
|
||||
|
||||
case VK_RETURN:
|
||||
scancode |= 0x0E00;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// logger(LOG_LEVEL_WARN, "%s [%u]: Test2, vk_code %li\n",
|
||||
// __FUNCTION__, __LINE__, vk_code);
|
||||
}
|
||||
}
|
||||
|
||||
return scancode;
|
||||
}
|
||||
|
||||
DWORD scancode_to_keycode(unsigned short scancode) {
|
||||
unsigned short keycode = 0x0000;
|
||||
|
||||
// Check the vk_code is in range.
|
||||
// NOTE vk_code >= 0 is assumed because the scancode is unsigned.
|
||||
if (scancode < 128) {
|
||||
keycode = keycode_scancode_table[scancode][1];
|
||||
}
|
||||
else {
|
||||
// Calculate the upper offset based on the lower half of the scancode + 128.
|
||||
unsigned short int i = (scancode & 0x007F) | 0x80;
|
||||
|
||||
if (i < sizeof(keycode_scancode_table) / sizeof(keycode_scancode_table[1])) {
|
||||
keycode = keycode_scancode_table[i][1];
|
||||
}
|
||||
}
|
||||
|
||||
return keycode;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
// Structure and pointers for the keyboard locale cache.
|
||||
typedef struct _KeyboardLocale {
|
||||
HKL id; // Locale ID
|
||||
HINSTANCE library; // Keyboard DLL instance.
|
||||
PVK_TO_BIT pVkToBit; // Pointers struct arrays.
|
||||
PVK_TO_WCHAR_TABLE pVkToWcharTable;
|
||||
PDEADKEY pDeadKey;
|
||||
struct _KeyboardLocale* next;
|
||||
} KeyboardLocale;
|
||||
|
||||
static KeyboardLocale* locale_first = NULL;
|
||||
static KeyboardLocale* locale_current = NULL;
|
||||
static WCHAR deadChar = WCH_NONE;
|
||||
|
||||
// Amount of pointer padding to apply for Wow64 instances.
|
||||
static unsigned short int ptr_padding = 0;
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
// Small function to check and see if we are executing under Wow64.
|
||||
static BOOL is_wow64() {
|
||||
BOOL status = FALSE;
|
||||
|
||||
LPFN_ISWOW64PROCESS pIsWow64Process = (LPFN_ISWOW64PROCESS)
|
||||
GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process");
|
||||
|
||||
if (pIsWow64Process != NULL) {
|
||||
HANDLE current_proc = GetCurrentProcess();
|
||||
|
||||
if (!pIsWow64Process(current_proc, &status)) {
|
||||
status = FALSE;
|
||||
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: pIsWow64Process(%#p, %#p) failed!\n",
|
||||
__FUNCTION__, __LINE__, current_proc, &status);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Locate the DLL that contains the current keyboard layout.
|
||||
static int get_keyboard_layout_file(char *layoutFile, DWORD bufferSize) {
|
||||
int status = IOHOOK_FAILURE;
|
||||
HKEY hKey;
|
||||
DWORD varType = REG_SZ;
|
||||
|
||||
char kbdName[KL_NAMELENGTH];
|
||||
if (GetKeyboardLayoutName(kbdName)) {
|
||||
char kbdKeyPath[51 + KL_NAMELENGTH];
|
||||
snprintf(kbdKeyPath, 51 + KL_NAMELENGTH, "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s", kbdName);
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR) kbdKeyPath, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
|
||||
if (RegQueryValueEx(hKey, "Layout File", NULL, &varType, (LPBYTE) layoutFile, &bufferSize) == ERROR_SUCCESS) {
|
||||
RegCloseKey(hKey);
|
||||
status = IOHOOK_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int refresh_locale_list() {
|
||||
int count = 0;
|
||||
|
||||
// Get the number of layouts the user has activated.
|
||||
int hkl_size = GetKeyboardLayoutList(0, NULL);
|
||||
if (hkl_size > 0) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: GetKeyboardLayoutList(0, NULL) found %i layouts.\n",
|
||||
__FUNCTION__, __LINE__, hkl_size);
|
||||
|
||||
// Get the thread id that currently has focus for our default.
|
||||
DWORD focus_pid = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
|
||||
HKL hlk_focus = GetKeyboardLayout(focus_pid);
|
||||
HKL hlk_default = GetKeyboardLayout(0);
|
||||
HKL *hkl_list = malloc(sizeof(HKL) * hkl_size);
|
||||
|
||||
int new_size = GetKeyboardLayoutList(hkl_size, hkl_list);
|
||||
if (new_size > 0) {
|
||||
if (new_size != hkl_size) {
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: Locale size mismatch! "
|
||||
"Expected %i, received %i!\n",
|
||||
__FUNCTION__, __LINE__, hkl_size, new_size);
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Received %i locales.\n",
|
||||
__FUNCTION__, __LINE__, new_size);
|
||||
}
|
||||
|
||||
KeyboardLocale* locale_previous = NULL;
|
||||
KeyboardLocale* locale_item = locale_first;
|
||||
|
||||
// Go though the linked list and remove KeyboardLocale's that are
|
||||
// no longer loaded.
|
||||
while (locale_item != NULL) {
|
||||
// Check to see if the old HKL is in the new list.
|
||||
bool is_loaded = false;
|
||||
int i;
|
||||
for (i = 0; i < new_size && !is_loaded; i++) {
|
||||
if (locale_item->id == hkl_list[i]) {
|
||||
// Flag and jump out of the loop.
|
||||
hkl_list[i] = NULL;
|
||||
is_loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (is_loaded) {
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Found locale ID %#p in the cache.\n",
|
||||
__FUNCTION__, __LINE__, locale_item->id);
|
||||
|
||||
// Set the previous local to the current locale.
|
||||
locale_previous = locale_item;
|
||||
|
||||
// Check and see if the locale is our current active locale.
|
||||
if (locale_item->id == hlk_focus) {
|
||||
locale_current = locale_item;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Removing locale ID %#p from the cache.\n",
|
||||
__FUNCTION__, __LINE__, locale_item->id);
|
||||
|
||||
// If the old id is not in the new list, remove it.
|
||||
locale_previous->next = locale_item->next;
|
||||
|
||||
// Make sure the locale_current points NULL or something valid.
|
||||
if (locale_item == locale_current) {
|
||||
locale_current = NULL;
|
||||
}
|
||||
|
||||
// Free the memory used by locale_item;
|
||||
free(locale_item);
|
||||
|
||||
// Set the item to the pervious item to guarantee a next.
|
||||
locale_item = locale_previous;
|
||||
}
|
||||
|
||||
// Iterate to the next linked list item.
|
||||
locale_item = locale_item->next;
|
||||
}
|
||||
|
||||
|
||||
// Insert anything new into the linked list.
|
||||
int i;
|
||||
for (i = 0; i < new_size; i++) {
|
||||
// Check to see if the item was already in the list.
|
||||
if (hkl_list[i] != NULL) {
|
||||
// Set the active keyboard layout for this thread to the HKL.
|
||||
ActivateKeyboardLayout(hkl_list[i], 0x00);
|
||||
|
||||
// Try to pull the current keyboard layout DLL from the registry.
|
||||
char layoutFile[MAX_PATH];
|
||||
if (get_keyboard_layout_file(layoutFile, sizeof(layoutFile)) == IOHOOK_SUCCESS) {
|
||||
// You can't trust the %SYSPATH%, look it up manually.
|
||||
char systemDirectory[MAX_PATH];
|
||||
if (GetSystemDirectory(systemDirectory, MAX_PATH) != 0) {
|
||||
char kbdLayoutFilePath[MAX_PATH];
|
||||
snprintf(kbdLayoutFilePath, MAX_PATH, "%s\\%s", systemDirectory, layoutFile);
|
||||
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Loading layout for %#p: %s.\n",
|
||||
__FUNCTION__, __LINE__, hkl_list[i], layoutFile);
|
||||
|
||||
// Create the new locale item.
|
||||
locale_item = malloc(sizeof(KeyboardLocale));
|
||||
locale_item->id = hkl_list[i];
|
||||
locale_item->library = LoadLibrary(kbdLayoutFilePath);
|
||||
|
||||
// Get the function pointer from the library to get the keyboard layer descriptor.
|
||||
KbdLayerDescriptor pKbdLayerDescriptor = (KbdLayerDescriptor) GetProcAddress(locale_item->library, "KbdLayerDescriptor");
|
||||
if (pKbdLayerDescriptor != NULL) {
|
||||
PKBDTABLES pKbd = pKbdLayerDescriptor();
|
||||
|
||||
// Store the memory address of the following 3 structures.
|
||||
BYTE *base = (BYTE *) pKbd;
|
||||
|
||||
// First element of each structure, no offset adjustment needed.
|
||||
locale_item->pVkToBit = pKbd->pCharModifiers->pVkToBit;
|
||||
|
||||
// Second element of pKbd, +4 byte offset on wow64.
|
||||
locale_item->pVkToWcharTable = *((PVK_TO_WCHAR_TABLE *) (base + offsetof(KBDTABLES, pVkToWcharTable) + ptr_padding));
|
||||
|
||||
// Third element of pKbd, +8 byte offset on wow64.
|
||||
locale_item->pDeadKey = *((PDEADKEY *) (base + offsetof(KBDTABLES, pDeadKey) + (ptr_padding * 2)));
|
||||
|
||||
// This will always be added to the end of the list.
|
||||
locale_item->next = NULL;
|
||||
|
||||
// Insert the item into the linked list.
|
||||
if (locale_previous == NULL) {
|
||||
// If nothing came before, the list is empty.
|
||||
locale_first = locale_item;
|
||||
}
|
||||
else {
|
||||
// Append the new locale to the end of the list.
|
||||
locale_previous->next = locale_item;
|
||||
}
|
||||
|
||||
// Check and see if the locale is our current active locale.
|
||||
if (locale_item->id == hlk_focus) {
|
||||
locale_current = locale_item;
|
||||
}
|
||||
|
||||
// Set the pervious locale item to the new one.
|
||||
locale_previous = locale_item;
|
||||
|
||||
count++;
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR,
|
||||
"%s [%u]: GetProcAddress() failed for KbdLayerDescriptor!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
|
||||
FreeLibrary(locale_item->library);
|
||||
free(locale_item);
|
||||
locale_item = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR,
|
||||
"%s [%u]: GetSystemDirectory() failed!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR,
|
||||
"%s [%u]: Could not find keyboard map for locale %#p!\n",
|
||||
__FUNCTION__, __LINE__, hkl_list[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR,
|
||||
"%s [%u]: GetKeyboardLayoutList() failed!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
|
||||
// TODO Try and recover by using the current layout.
|
||||
// Hint: Use locale_id instead of hkl_list[i] in the loop above.
|
||||
}
|
||||
|
||||
free(hkl_list);
|
||||
ActivateKeyboardLayout(hlk_default, 0x00);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
SIZE_T keycode_to_unicode(DWORD keycode, PWCHAR buffer, SIZE_T size) {
|
||||
// Get the thread id that currently has focus and ask for its current
|
||||
// locale.
|
||||
DWORD focus_pid = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
|
||||
HKL locale_id = GetKeyboardLayout(focus_pid);
|
||||
|
||||
// If the current Locale is not the new locale, search the linked list.
|
||||
if (locale_current == NULL || locale_current->id != locale_id) {
|
||||
locale_current = NULL;
|
||||
KeyboardLocale* locale_item = locale_first;
|
||||
|
||||
// Search the linked list...
|
||||
while (locale_item != NULL && locale_item->id != locale_id) {
|
||||
locale_item = locale_item->next;
|
||||
}
|
||||
|
||||
// You may already be a winner!
|
||||
if (locale_item != NULL && locale_item->id != locale_id) {
|
||||
logger(LOG_LEVEL_INFO,
|
||||
"%s [%u]: Activating keyboard layout %#p.\n",
|
||||
__FUNCTION__, __LINE__, locale_item->id);
|
||||
|
||||
// Switch the current locale.
|
||||
locale_current = locale_item;
|
||||
locale_item = NULL;
|
||||
|
||||
// If they layout changes the dead key state needs to be reset.
|
||||
// This is consistent with the way Windows handles locale changes.
|
||||
deadChar = WCH_NONE;
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_DEBUG,
|
||||
"%s [%u]: Refreshing locale cache.\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
|
||||
refresh_locale_list();
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize to empty.
|
||||
SIZE_T charCount = 0;
|
||||
// buffer[i] = WCH_NONE;
|
||||
|
||||
// Check and make sure the Unicode helper was loaded.
|
||||
if (locale_current != NULL) {
|
||||
logger(LOG_LEVEL_INFO,
|
||||
"%s [%u]: Using keyboard layout %#p.\n",
|
||||
__FUNCTION__, __LINE__, locale_current->id);
|
||||
|
||||
int mod = 0;
|
||||
|
||||
int capsLock = (GetKeyState(VK_CAPITAL) & 0x01);
|
||||
|
||||
PVK_TO_BIT pVkToBit = locale_current->pVkToBit;
|
||||
PVK_TO_WCHAR_TABLE pVkToWcharTable = locale_current->pVkToWcharTable;
|
||||
PDEADKEY pDeadKey = locale_current->pDeadKey;
|
||||
|
||||
/* Loop over the modifier keys for this locale and determine what is
|
||||
* currently depressed. Because this is only a structure of two
|
||||
* bytes, we don't need to worry about the structure padding of __ptr64
|
||||
* offsets on Wow64.
|
||||
*/
|
||||
bool is_shift = false, is_ctrl = false, is_alt = false;
|
||||
int i;
|
||||
for (i = 0; pVkToBit[i].Vk != 0; i++) {
|
||||
short state = GetAsyncKeyState(pVkToBit[i].Vk);
|
||||
|
||||
// Check to see if the most significant bit is active.
|
||||
if (state & ~SHRT_MAX) {
|
||||
if (pVkToBit[i].Vk == VK_SHIFT) {
|
||||
is_shift = true;
|
||||
}
|
||||
else if (pVkToBit[i].Vk == VK_CONTROL) {
|
||||
is_ctrl = true;
|
||||
}
|
||||
else if (pVkToBit[i].Vk == VK_MENU) {
|
||||
is_alt = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check the Shift modifier.
|
||||
if (is_shift) {
|
||||
mod = 1;
|
||||
}
|
||||
|
||||
// Check for the AltGr modifier.
|
||||
if (is_ctrl && is_alt) {
|
||||
mod += 3;
|
||||
}
|
||||
|
||||
// Default 32 bit structure size should be 6 bytes (4 for the pointer and 2
|
||||
// additional byte fields) that are padded out to 8 bytes by the compiler.
|
||||
unsigned short sizeVkToWcharTable = sizeof(VK_TO_WCHAR_TABLE);
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
if (is_wow64()) {
|
||||
// If we are running under Wow64 the size of the first pointer will be
|
||||
// 8 bringing the total size to 10 bytes padded out to 16.
|
||||
sizeVkToWcharTable = (sizeVkToWcharTable + ptr_padding + 7) & -8;
|
||||
}
|
||||
#endif
|
||||
|
||||
BYTE *ptrCurrentVkToWcharTable = (BYTE *) pVkToWcharTable;
|
||||
|
||||
int cbSize, n;
|
||||
do {
|
||||
// cbSize is used to calculate n, and n is used for the size of pVkToWchars[j].wch[n]
|
||||
cbSize = *(ptrCurrentVkToWcharTable + offsetof(VK_TO_WCHAR_TABLE, cbSize) + ptr_padding);
|
||||
n = (cbSize - 2) / 2;
|
||||
|
||||
// Same as VK_TO_WCHARS pVkToWchars[] = pVkToWcharTable[i].pVkToWchars
|
||||
PVK_TO_WCHARS pVkToWchars = (PVK_TO_WCHARS) ((PVK_TO_WCHAR_TABLE) ptrCurrentVkToWcharTable)->pVkToWchars;
|
||||
|
||||
if (pVkToWchars != NULL && mod < n) {
|
||||
// pVkToWchars[j].VirtualKey
|
||||
BYTE *pCurrentVkToWchars = (BYTE *) pVkToWchars;
|
||||
|
||||
do {
|
||||
if (((PVK_TO_WCHARS) pCurrentVkToWchars)->VirtualKey == keycode) {
|
||||
if ((((PVK_TO_WCHARS) pCurrentVkToWchars)->Attributes == CAPLOK) && capsLock) {
|
||||
if (is_shift && mod > 0) {
|
||||
mod -= 1;
|
||||
}
|
||||
else {
|
||||
mod += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the initial unicode char.
|
||||
WCHAR unicode = ((PVK_TO_WCHARS) pCurrentVkToWchars)->wch[mod];
|
||||
|
||||
// Increment the pCurrentVkToWchars by the size of wch[n].
|
||||
pCurrentVkToWchars += sizeof(VK_TO_WCHARS) + (sizeof(WCHAR) * n);
|
||||
|
||||
|
||||
if (unicode == WCH_DEAD) {
|
||||
// The current unicode char is a dead key...
|
||||
if (deadChar == WCH_NONE) {
|
||||
// No previous dead key was set so cache the next
|
||||
// wchar so we know what to do next time its pressed.
|
||||
deadChar = ((PVK_TO_WCHARS) pCurrentVkToWchars)->wch[mod];
|
||||
}
|
||||
else {
|
||||
if (size >= 2) {
|
||||
// Received a second dead key.
|
||||
memset(buffer, deadChar, 2);
|
||||
//buffer[0] = deadChar;
|
||||
//buffer[1] = deadChar;
|
||||
|
||||
deadChar = WCH_NONE;
|
||||
charCount = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (unicode != WCH_NONE) {
|
||||
// We are not WCH_NONE or WCH_DEAD
|
||||
if (size >= 1) {
|
||||
buffer[0] = unicode;
|
||||
charCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// Add sizeof WCHAR because we are really an array of WCHAR[n] not WCHAR[]
|
||||
pCurrentVkToWchars += sizeof(VK_TO_WCHARS) + (sizeof(WCHAR) * n);
|
||||
}
|
||||
} while ( ((PVK_TO_WCHARS) pCurrentVkToWchars)->VirtualKey != 0 );
|
||||
}
|
||||
|
||||
// This is effectively the same as: ptrCurrentVkToWcharTable = pVkToWcharTable[++i];
|
||||
ptrCurrentVkToWcharTable += sizeVkToWcharTable;
|
||||
} while (cbSize != 0);
|
||||
|
||||
|
||||
// If the current local has a dead key set.
|
||||
if (deadChar != WCH_NONE) {
|
||||
// Loop over the pDeadKey lookup table for the locale.
|
||||
int i;
|
||||
for (i = 0; pDeadKey[i].dwBoth != 0; i++) {
|
||||
WCHAR baseChar = (WCHAR) pDeadKey[i].dwBoth;
|
||||
WCHAR diacritic = (WCHAR) (pDeadKey[i].dwBoth >> 16);
|
||||
|
||||
// If we locate an extended dead char, set it.
|
||||
if (size >= 1 && baseChar == buffer[0] && diacritic == deadChar) {
|
||||
deadChar = WCH_NONE;
|
||||
|
||||
if (charCount <= size) {
|
||||
memset(buffer, (WCHAR) pDeadKey[i].wchComposed, charCount);
|
||||
//buffer[i] = (WCHAR) pDeadKey[i].wchComposed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return charCount;
|
||||
}
|
||||
|
||||
int load_input_helper() {
|
||||
int count = 0;
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
if (is_wow64()) {
|
||||
ptr_padding = sizeof(void *);
|
||||
}
|
||||
#endif
|
||||
|
||||
count = refresh_locale_list();
|
||||
|
||||
logger(LOG_LEVEL_INFO,
|
||||
"%s [%u]: refresh_locale_list() found %i locale(s).\n",
|
||||
__FUNCTION__, __LINE__, count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// This returns the number of locales that were removed.
|
||||
int unload_input_helper() {
|
||||
int count = 0;
|
||||
|
||||
// Cleanup and free memory from the old list.
|
||||
KeyboardLocale* locale_item = locale_first;
|
||||
while (locale_item != NULL) {
|
||||
// Remove the first item from the linked list.
|
||||
FreeLibrary(locale_item->library);
|
||||
locale_first = locale_item->next;
|
||||
free(locale_item);
|
||||
locale_item = locale_first;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
// Reset the current local.
|
||||
locale_current = NULL;
|
||||
|
||||
return count;
|
||||
}
|
211
vendor/github.com/robotn/gohook/hook/windows/properties_c.h
generated
vendored
Normal file
211
vendor/github.com/robotn/gohook/hook/windows/properties_c.h
generated
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include "../iohook.h"
|
||||
#include "input.h"
|
||||
// #include "logger.h"
|
||||
|
||||
// The handle to the DLL module pulled in DllMain on DLL_PROCESS_ATTACH.
|
||||
HINSTANCE hInst;
|
||||
|
||||
// input_hook.c
|
||||
extern void unregister_running_hooks();
|
||||
|
||||
|
||||
// Structure for the monitor_enum_proc() callback so we can track the count.
|
||||
typedef struct _screen_info {
|
||||
uint8_t count;
|
||||
screen_data *data;
|
||||
} screen_info;
|
||||
|
||||
|
||||
static BOOL CALLBACK monitor_enum_proc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
|
||||
int width = lprcMonitor->right - lprcMonitor->left;
|
||||
int height = lprcMonitor->bottom - lprcMonitor->top;
|
||||
int origin_x = lprcMonitor->left;
|
||||
int origin_y = lprcMonitor->top;
|
||||
|
||||
if (width > 0 && height > 0) {
|
||||
screen_info *screens = (screen_info *) dwData;
|
||||
|
||||
if (screens->data == NULL) {
|
||||
screens->data = (screen_data *) malloc(sizeof(screen_data));
|
||||
}
|
||||
else {
|
||||
screens->data = (screen_data *) realloc(screens, sizeof(screen_data) * screens->count);
|
||||
}
|
||||
|
||||
screens->data[screens->count++] = (screen_data) {
|
||||
// Should monitor count start @ zero? Currently it starts at 1.
|
||||
.number = screens->count,
|
||||
.x = origin_x,
|
||||
.y = origin_y,
|
||||
.width = width,
|
||||
.height = height
|
||||
};
|
||||
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: Monitor %d: %ldx%ld (%ld, %ld)\n",
|
||||
__FUNCTION__, __LINE__, screens->count, width, height, origin_x, origin_y);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
IOHOOK_API screen_data* hook_create_screen_info(unsigned char *count) {
|
||||
// Initialize count to zero.
|
||||
*count = 0;
|
||||
|
||||
// Create a simple structure to make working with monitor_enum_proc easier.
|
||||
screen_info screens = {
|
||||
.count = 0,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
BOOL status = EnumDisplayMonitors(NULL, NULL, monitor_enum_proc, (LPARAM) &screens);
|
||||
|
||||
if (!status || screens.count == 0) {
|
||||
// Fallback in case EnumDisplayMonitors fails.
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: EnumDisplayMonitors failed. Fallback.\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
|
||||
int width = GetSystemMetrics(SM_CXSCREEN);
|
||||
int height = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
if (width > 0 && height > 0) {
|
||||
screens.data = (screen_data *) malloc(sizeof(screen_data));
|
||||
|
||||
if (screens.data != NULL) {
|
||||
*count = 1;
|
||||
screens.data[0] = (screen_data) {
|
||||
.number = 1,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = width,
|
||||
.height = height
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Populate the count.
|
||||
*count = screens.count;
|
||||
}
|
||||
|
||||
return screens.data;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_auto_repeat_rate() {
|
||||
long int value = -1;
|
||||
long int rate;
|
||||
|
||||
if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &rate, 0)) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: SPI_GETKEYBOARDSPEED: %li.\n",
|
||||
__FUNCTION__, __LINE__, rate);
|
||||
|
||||
value = rate;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_auto_repeat_delay() {
|
||||
long int value = -1;
|
||||
long int delay;
|
||||
|
||||
if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &delay, 0)) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: SPI_GETKEYBOARDDELAY: %li.\n",
|
||||
__FUNCTION__, __LINE__, delay);
|
||||
|
||||
value = delay;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_pointer_acceleration_multiplier() {
|
||||
long int value = -1;
|
||||
int mouse[3]; // 0-Threshold X, 1-Threshold Y and 2-Speed.
|
||||
|
||||
if (SystemParametersInfo(SPI_GETMOUSE, 0, &mouse, 0)) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: SPI_GETMOUSE[2]: %i.\n",
|
||||
__FUNCTION__, __LINE__, mouse[2]);
|
||||
|
||||
value = mouse[2];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_pointer_acceleration_threshold() {
|
||||
long int value = -1;
|
||||
int mouse[3]; // 0-Threshold X, 1-Threshold Y and 2-Speed.
|
||||
|
||||
if (SystemParametersInfo(SPI_GETMOUSE, 0, &mouse, 0)) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: SPI_GETMOUSE[0]: %i.\n",
|
||||
__FUNCTION__, __LINE__, mouse[0]);
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: SPI_GETMOUSE[1]: %i.\n",
|
||||
__FUNCTION__, __LINE__, mouse[1]);
|
||||
|
||||
// Average the x and y thresholds.
|
||||
value = (mouse[0] + mouse[1]) / 2;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_pointer_sensitivity() {
|
||||
long int value = -1;
|
||||
int sensitivity;
|
||||
|
||||
if (SystemParametersInfo(SPI_GETMOUSESPEED, 0, &sensitivity, 0)) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: SPI_GETMOUSESPEED: %i.\n",
|
||||
__FUNCTION__, __LINE__, sensitivity);
|
||||
|
||||
value = sensitivity;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_multi_click_time() {
|
||||
long int value = -1;
|
||||
UINT clicktime;
|
||||
|
||||
clicktime = GetDoubleClickTime();
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: GetDoubleClickTime: %u.\n",
|
||||
__FUNCTION__, __LINE__, (unsigned int) clicktime);
|
||||
|
||||
value = (long int) clicktime;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// DLL Entry point.
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) {
|
||||
switch (fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
// Save the DLL address.
|
||||
hInst = hInstDLL;
|
||||
|
||||
// Initialize native input helper functions.
|
||||
load_input_helper();
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
// Unregister any hooks that may still be installed.
|
||||
unregister_running_hooks();
|
||||
|
||||
// Deinitialize native input helper functions.
|
||||
unload_input_helper();
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
// Do Nothing.
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
386
vendor/github.com/robotn/gohook/hook/x11/event_c.h
generated
vendored
Normal file
386
vendor/github.com/robotn/gohook/hook/x11/event_c.h
generated
vendored
Normal file
@ -0,0 +1,386 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#ifdef USE_XTEST
|
||||
#include <X11/extensions/XTest.h>
|
||||
#endif
|
||||
|
||||
#include "../iohook.h"
|
||||
#include "input.h"
|
||||
// #include "../logger.h"
|
||||
|
||||
extern Display *properties_disp;
|
||||
|
||||
// This lookup table must be in the same order the masks are defined.
|
||||
#ifdef USE_XTEST
|
||||
static KeySym keymask_lookup[8] = {
|
||||
XK_Shift_L,
|
||||
XK_Control_L,
|
||||
XK_Meta_L,
|
||||
XK_Alt_L,
|
||||
|
||||
XK_Shift_R,
|
||||
XK_Control_R,
|
||||
XK_Meta_R,
|
||||
XK_Alt_R
|
||||
};
|
||||
|
||||
static unsigned int btnmask_lookup[5] = {
|
||||
MASK_BUTTON1,
|
||||
MASK_BUTTON2,
|
||||
MASK_BUTTON3,
|
||||
MASK_BUTTON4,
|
||||
MASK_BUTTON5
|
||||
};
|
||||
#else
|
||||
// TODO Possibly relocate to input helper.
|
||||
static unsigned int convert_to_native_mask(unsigned int mask) {
|
||||
unsigned int native_mask = 0x00;
|
||||
|
||||
if (mask & (MASK_SHIFT)) { native_mask |= ShiftMask; }
|
||||
if (mask & (MASK_CTRL)) { native_mask |= ControlMask; }
|
||||
if (mask & (MASK_META)) { native_mask |= Mod4Mask; }
|
||||
if (mask & (MASK_ALT)) { native_mask |= Mod1Mask; }
|
||||
|
||||
if (mask & MASK_BUTTON1) { native_mask |= Button1Mask; }
|
||||
if (mask & MASK_BUTTON2) { native_mask |= Button2Mask; }
|
||||
if (mask & MASK_BUTTON3) { native_mask |= Button3Mask; }
|
||||
if (mask & MASK_BUTTON4) { native_mask |= Button4Mask; }
|
||||
if (mask & MASK_BUTTON5) { native_mask |= Button5Mask; }
|
||||
|
||||
return native_mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void post_key_event(iohook_event * const event) {
|
||||
#ifdef USE_XTEST
|
||||
// FIXME Currently ignoring EVENT_KEY_TYPED.
|
||||
if (event->type == EVENT_KEY_PRESSED) {
|
||||
XTestFakeKeyEvent(
|
||||
properties_disp,
|
||||
scancode_to_keycode(event->data.keyboard.keycode),
|
||||
True,
|
||||
0);
|
||||
}
|
||||
else if (event->type == EVENT_KEY_RELEASED) {
|
||||
XTestFakeKeyEvent(
|
||||
properties_disp,
|
||||
scancode_to_keycode(event->data.keyboard.keycode),
|
||||
False,
|
||||
0);
|
||||
}
|
||||
#else
|
||||
XKeyEvent key_event;
|
||||
|
||||
key_event.serial = 0x00;
|
||||
key_event.send_event = False;
|
||||
key_event.display = properties_disp;
|
||||
key_event.time = CurrentTime;
|
||||
key_event.same_screen = True;
|
||||
|
||||
unsigned int mask;
|
||||
if (!XQueryPointer(properties_disp, DefaultRootWindow(properties_disp), &(key_event.root), &(key_event.subwindow), &(key_event.x_root), &(key_event.y_root), &(key_event.x), &(key_event.y), &mask)) {
|
||||
key_event.root = DefaultRootWindow(properties_disp);
|
||||
key_event.window = key_event.root;
|
||||
key_event.subwindow = None;
|
||||
|
||||
key_event.x_root = 0;
|
||||
key_event.y_root = 0;
|
||||
key_event.x = 0;
|
||||
key_event.y = 0;
|
||||
}
|
||||
|
||||
key_event.state = convert_to_native_mask(event->mask);
|
||||
key_event.keycode = XKeysymToKeycode(properties_disp, scancode_to_keycode(event->data.keyboard.keycode));
|
||||
|
||||
// FIXME Currently ignoring typed events.
|
||||
if (event->type == EVENT_KEY_PRESSED) {
|
||||
key_event.type = KeyPress;
|
||||
XSendEvent(properties_disp, InputFocus, False, KeyPressMask, (XEvent *) &key_event);
|
||||
}
|
||||
else if (event->type == EVENT_KEY_RELEASED) {
|
||||
key_event.type = KeyRelease;
|
||||
XSendEvent(properties_disp, InputFocus, False, KeyReleaseMask, (XEvent *) &key_event);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void post_mouse_button_event(iohook_event * const event) {
|
||||
#ifdef USE_XTEST
|
||||
Window ret_root;
|
||||
Window ret_child;
|
||||
int root_x;
|
||||
int root_y;
|
||||
int win_x;
|
||||
int win_y;
|
||||
unsigned int mask;
|
||||
|
||||
Window win_root = XDefaultRootWindow(properties_disp);
|
||||
Bool query_status = XQueryPointer(properties_disp, win_root, &ret_root, &ret_child, &root_x, &root_y, &win_x, &win_y, &mask);
|
||||
if (query_status) {
|
||||
if (event->data.mouse.x != root_x || event->data.mouse.y != root_y) {
|
||||
// Move the pointer to the specified position.
|
||||
XTestFakeMotionEvent(properties_disp, -1, event->data.mouse.x, event->data.mouse.y, 0);
|
||||
}
|
||||
else {
|
||||
query_status = False;
|
||||
}
|
||||
}
|
||||
|
||||
if (event->type == EVENT_MOUSE_WHEEL) {
|
||||
// Wheel events should be the same as click events on X11.
|
||||
// type, amount and rotation
|
||||
if (event->data.wheel.rotation < 0) {
|
||||
XTestFakeButtonEvent(properties_disp, WheelUp, True, 0);
|
||||
XTestFakeButtonEvent(properties_disp, WheelUp, False, 0);
|
||||
}
|
||||
else {
|
||||
XTestFakeButtonEvent(properties_disp, WheelDown, True, 0);
|
||||
XTestFakeButtonEvent(properties_disp, WheelDown, False, 0);
|
||||
}
|
||||
}
|
||||
else if (event->type == EVENT_MOUSE_PRESSED) {
|
||||
XTestFakeButtonEvent(properties_disp, event->data.mouse.button, True, 0);
|
||||
}
|
||||
else if (event->type == EVENT_MOUSE_RELEASED) {
|
||||
XTestFakeButtonEvent(properties_disp, event->data.mouse.button, False, 0);
|
||||
}
|
||||
else if (event->type == EVENT_MOUSE_CLICKED) {
|
||||
XTestFakeButtonEvent(properties_disp, event->data.mouse.button, True, 0);
|
||||
XTestFakeButtonEvent(properties_disp, event->data.mouse.button, False, 0);
|
||||
}
|
||||
|
||||
if (query_status) {
|
||||
// Move the pointer back to the original position.
|
||||
XTestFakeMotionEvent(properties_disp, -1, root_x, root_y, 0);
|
||||
}
|
||||
#else
|
||||
XButtonEvent btn_event;
|
||||
|
||||
btn_event.serial = 0x00;
|
||||
btn_event.send_event = False;
|
||||
btn_event.display = properties_disp;
|
||||
btn_event.time = CurrentTime;
|
||||
btn_event.same_screen = True;
|
||||
|
||||
btn_event.root = DefaultRootWindow(properties_disp);
|
||||
btn_event.window = btn_event.root;
|
||||
btn_event.subwindow = None;
|
||||
|
||||
btn_event.type = 0x00;
|
||||
btn_event.state = 0x00;
|
||||
btn_event.x_root = 0;
|
||||
btn_event.y_root = 0;
|
||||
btn_event.x = 0;
|
||||
btn_event.y = 0;
|
||||
btn_event.button = 0x00;
|
||||
|
||||
btn_event.state = convert_to_native_mask(event->mask);
|
||||
|
||||
btn_event.x = event->data.mouse.x;
|
||||
btn_event.y = event->data.mouse.y;
|
||||
|
||||
#if defined(USE_XINERAMA) || defined(USE_XRANDR)
|
||||
uint8_t screen_count;
|
||||
screen_data *screens = hook_create_screen_info(&screen_count);
|
||||
if (screen_count > 1) {
|
||||
btn_event.x += screens[0].x;
|
||||
btn_event.y += screens[0].y;
|
||||
}
|
||||
|
||||
if (screens != NULL) {
|
||||
free(screens);
|
||||
}
|
||||
#endif
|
||||
|
||||
// These are the same because Window == Root Window.
|
||||
btn_event.x_root = btn_event.x;
|
||||
btn_event.y_root = btn_event.y;
|
||||
|
||||
if (event->type == EVENT_MOUSE_WHEEL) {
|
||||
// type, amount and rotation
|
||||
if (event->data.wheel.rotation < 0) {
|
||||
btn_event.button = WheelUp;
|
||||
}
|
||||
else {
|
||||
btn_event.button = WheelDown;
|
||||
}
|
||||
}
|
||||
|
||||
if (event->type != EVENT_MOUSE_RELEASED) {
|
||||
// FIXME Where do we set event->button?
|
||||
btn_event.type = ButtonPress;
|
||||
XSendEvent(properties_disp, InputFocus, False, ButtonPressMask, (XEvent *) &btn_event);
|
||||
}
|
||||
|
||||
if (event->type != EVENT_MOUSE_PRESSED) {
|
||||
btn_event.type = ButtonRelease;
|
||||
XSendEvent(properties_disp, InputFocus, False, ButtonReleaseMask, (XEvent *) &btn_event);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void post_mouse_motion_event(iohook_event * const event) {
|
||||
#ifdef USE_XTEST
|
||||
XTestFakeMotionEvent(properties_disp, -1, event->data.mouse.x, event->data.mouse.y, 0);
|
||||
#else
|
||||
XMotionEvent mov_event;
|
||||
|
||||
mov_event.serial = MotionNotify;
|
||||
mov_event.send_event = False;
|
||||
mov_event.display = properties_disp;
|
||||
mov_event.time = CurrentTime;
|
||||
mov_event.same_screen = True;
|
||||
mov_event.is_hint = NotifyNormal,
|
||||
mov_event.root = DefaultRootWindow(properties_disp);
|
||||
mov_event.window = mov_event.root;
|
||||
mov_event.subwindow = None;
|
||||
|
||||
mov_event.type = 0x00;
|
||||
mov_event.state = 0x00;
|
||||
mov_event.x_root = 0;
|
||||
mov_event.y_root = 0;
|
||||
mov_event.x = 0;
|
||||
mov_event.y = 0;
|
||||
|
||||
mov_event.state = convert_to_native_mask(event->mask);
|
||||
|
||||
mov_event.x = event->data.mouse.x;
|
||||
mov_event.y = event->data.mouse.y;
|
||||
|
||||
#if defined(USE_XINERAMA) || defined(USE_XRANDR)
|
||||
uint8_t screen_count;
|
||||
screen_data *screens = hook_create_screen_info(&screen_count);
|
||||
if (screen_count > 1) {
|
||||
mov_event.x += screens[0].x;
|
||||
mov_event.y += screens[0].y;
|
||||
}
|
||||
|
||||
if (screens != NULL) {
|
||||
free(screens);
|
||||
}
|
||||
#endif
|
||||
|
||||
// These are the same because Window == Root Window.
|
||||
mov_event.x_root = mov_event.x;
|
||||
mov_event.y_root = mov_event.y;
|
||||
|
||||
long int event_mask = NoEventMask;
|
||||
if (event->type == EVENT_MOUSE_DRAGGED) {
|
||||
#if Button1Mask == Button1MotionMask && \
|
||||
Button2Mask == Button2MotionMask && \
|
||||
Button3Mask == Button3MotionMask && \
|
||||
Button4Mask == Button4MotionMask && \
|
||||
Button5Mask == Button5MotionMask
|
||||
// This little trick only works if Button#MotionMasks align with
|
||||
// the Button#Masks.
|
||||
event_mask = mov_event.state &
|
||||
(Button1MotionMask | Button2MotionMask |
|
||||
Button2MotionMask | Button3MotionMask | Button5MotionMask);
|
||||
#else
|
||||
// Fallback to some slightly larger...
|
||||
if (event->state & Button1Mask) {
|
||||
event_mask |= Button1MotionMask;
|
||||
}
|
||||
|
||||
if (event->state & Button2Mask) {
|
||||
event_mask |= Button2MotionMask;
|
||||
}
|
||||
|
||||
if (event->state & Button3Mask) {
|
||||
event_mask |= Button3MotionMask;
|
||||
}
|
||||
|
||||
if (event->state & Button4Mask) {
|
||||
event_mask |= Button4MotionMask;
|
||||
}
|
||||
|
||||
if (event->state & Button5Mask) {
|
||||
event_mask |= Button5MotionMask;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// NOTE x_mask = NoEventMask.
|
||||
XSendEvent(properties_disp, InputFocus, False, event_mask, (XEvent *) &mov_event);
|
||||
#endif
|
||||
}
|
||||
|
||||
IOHOOK_API void hook_post_event(iohook_event * const event) {
|
||||
XLockDisplay(properties_disp);
|
||||
|
||||
#ifdef USE_XTEST
|
||||
// XTest does not have modifier support, so we fake it by depressing the
|
||||
// appropriate modifier keys.
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(keymask_lookup) / sizeof(KeySym); i++) {
|
||||
if (event->mask & 1 << i) {
|
||||
XTestFakeKeyEvent(properties_disp, XKeysymToKeycode(properties_disp, keymask_lookup[i]), True, 0);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(btnmask_lookup) / sizeof(unsigned int); i++) {
|
||||
if (event->mask & btnmask_lookup[i]) {
|
||||
XTestFakeButtonEvent(properties_disp, i + 1, True, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (event->type) {
|
||||
case EVENT_KEY_PRESSED:
|
||||
case EVENT_KEY_RELEASED:
|
||||
case EVENT_KEY_TYPED:
|
||||
post_key_event(event);
|
||||
break;
|
||||
|
||||
case EVENT_MOUSE_PRESSED:
|
||||
case EVENT_MOUSE_RELEASED:
|
||||
case EVENT_MOUSE_WHEEL:
|
||||
case EVENT_MOUSE_CLICKED:
|
||||
post_mouse_button_event(event);
|
||||
break;
|
||||
|
||||
case EVENT_MOUSE_DRAGGED:
|
||||
case EVENT_MOUSE_MOVED:
|
||||
post_mouse_motion_event(event);
|
||||
break;
|
||||
|
||||
case EVENT_HOOK_ENABLED:
|
||||
case EVENT_HOOK_DISABLED:
|
||||
// Ignore hook enabled / disabled events.
|
||||
|
||||
default:
|
||||
// Ignore any other garbage.
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: Ignoring post event type %#X\n",
|
||||
__FUNCTION__, __LINE__, event->type);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef USE_XTEST
|
||||
// Release the previously held modifier keys used to fake the event mask.
|
||||
unsigned int i ;
|
||||
for (i= 0; i < sizeof(keymask_lookup) / sizeof(KeySym); i++) {
|
||||
if (event->mask & 1 << i) {
|
||||
XTestFakeKeyEvent(properties_disp, XKeysymToKeycode(properties_disp, keymask_lookup[i]), False, 0);
|
||||
}
|
||||
}
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(btnmask_lookup) / sizeof(unsigned int); i++) {
|
||||
if (event->mask & btnmask_lookup[i]) {
|
||||
XTestFakeButtonEvent(properties_disp, i + 1, False, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Don't forget to flush!
|
||||
XSync(properties_disp, True);
|
||||
XUnlockDisplay(properties_disp);
|
||||
}
|
1132
vendor/github.com/robotn/gohook/hook/x11/hook_c.h
generated
vendored
Normal file
1132
vendor/github.com/robotn/gohook/hook/x11/hook_c.h
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
86
vendor/github.com/robotn/gohook/hook/x11/input.h
generated
vendored
Normal file
86
vendor/github.com/robotn/gohook/hook/x11/input.h
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
|
||||
#define USE_XKBCOMMON 0
|
||||
//#define _included_input_helper 0
|
||||
#ifndef _included_input_helper
|
||||
#define _included_input_helper
|
||||
|
||||
#include <stdint.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#ifdef USE_XKBCOMMON
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-x11.h>
|
||||
#endif
|
||||
|
||||
|
||||
// Virtual button codes that are not defined by X11.
|
||||
#define Button1 1
|
||||
#define Button2 2
|
||||
#define Button3 3
|
||||
#define WheelUp 4
|
||||
#define WheelDown 5
|
||||
#define WheelLeft 6
|
||||
#define WheelRight 7
|
||||
#define XButton1 8
|
||||
#define XButton2 9
|
||||
|
||||
/* Converts an X11 key symbol to a single Unicode character. No direct X11
|
||||
* functionality exists to provide this information.
|
||||
*/
|
||||
extern size_t keysym_to_unicode(KeySym keysym, uint16_t *buffer, size_t size);
|
||||
|
||||
/* Convert a single Unicode character to an X11 key symbol. This function
|
||||
* provides a better translation than XStringToKeysym() for Unicode characters.
|
||||
*/
|
||||
extern KeySym unicode_to_keysym(uint16_t unicode);
|
||||
|
||||
/* Converts an X11 key code to the appropriate keyboard scan code.
|
||||
*/
|
||||
extern uint16_t keycode_to_scancode(KeyCode keycode);
|
||||
|
||||
/* Converts a keyboard scan code to the appropriate X11 key code.
|
||||
*/
|
||||
extern KeyCode scancode_to_keycode(uint16_t scancode);
|
||||
|
||||
|
||||
#ifdef USE_XKBCOMMON
|
||||
|
||||
/* Converts an X11 key code to a Unicode character sequence. libXKBCommon support
|
||||
* is required for this method.
|
||||
*/
|
||||
extern size_t keycode_to_unicode(struct xkb_state* state, KeyCode keycode, uint16_t *buffer, size_t size);
|
||||
|
||||
/* Create a xkb_state structure and return a pointer to it.
|
||||
*/
|
||||
extern struct xkb_state * create_xkb_state(struct xkb_context *context, xcb_connection_t *connection);
|
||||
|
||||
/* Release xkb_state structure created by create_xkb_state().
|
||||
*/
|
||||
extern void destroy_xkb_state(struct xkb_state* state);
|
||||
|
||||
#else
|
||||
|
||||
/* Converts an X11 key code and event mask to the appropriate X11 key symbol.
|
||||
* This functions in much the same way as XKeycodeToKeysym() but allows for a
|
||||
* faster and more flexible lookup.
|
||||
*/
|
||||
extern KeySym keycode_to_keysym(KeyCode keycode, unsigned int modifier_mask);
|
||||
|
||||
#endif
|
||||
|
||||
/* Initialize items required for KeyCodeToKeySym() and KeySymToUnicode()
|
||||
* functionality. This method is called by OnLibraryLoad() and may need to be
|
||||
* called in combination with UnloadInputHelper() if the native keyboard layout
|
||||
* is changed.
|
||||
*/
|
||||
extern void load_input_helper();
|
||||
|
||||
/* De-initialize items required for KeyCodeToKeySym() and KeySymToUnicode()
|
||||
* functionality. This method is called by OnLibraryUnload() and may need to be
|
||||
* called in combination with LoadInputHelper() if the native keyboard layout
|
||||
* is changed.
|
||||
*/
|
||||
extern void unload_input_helper();
|
||||
|
||||
#endif
|
1970
vendor/github.com/robotn/gohook/hook/x11/input_c.h
generated
vendored
Normal file
1970
vendor/github.com/robotn/gohook/hook/x11/input_c.h
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
499
vendor/github.com/robotn/gohook/hook/x11/properties_c.h
generated
vendored
Normal file
499
vendor/github.com/robotn/gohook/hook/x11/properties_c.h
generated
vendored
Normal file
@ -0,0 +1,499 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <X11/Xlib.h>
|
||||
#ifdef USE_XKB
|
||||
#include <X11/XKBlib.h>
|
||||
#endif
|
||||
#ifdef USE_XF86MISC
|
||||
#include <X11/extensions/xf86misc.h>
|
||||
#include <X11/extensions/xf86mscstr.h>
|
||||
#endif
|
||||
#if defined(USE_XINERAMA) && !defined(USE_XRANDR)
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#elif defined(USE_XRANDR)
|
||||
#include <pthread.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#endif
|
||||
#ifdef USE_XT
|
||||
#include <X11/Intrinsic.h>
|
||||
|
||||
static XtAppContext xt_context;
|
||||
static Display *xt_disp;
|
||||
#endif
|
||||
|
||||
#include "../iohook.h"
|
||||
#include "input.h"
|
||||
// #include "../logger.h"
|
||||
|
||||
Display *properties_disp;
|
||||
|
||||
#ifdef USE_XRANDR
|
||||
static pthread_mutex_t xrandr_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static XRRScreenResources *xrandr_resources = NULL;
|
||||
|
||||
static void settings_cleanup_proc(void *arg) {
|
||||
if (pthread_mutex_trylock(&xrandr_mutex) == 0) {
|
||||
if (xrandr_resources != NULL) {
|
||||
XRRFreeScreenResources(xrandr_resources);
|
||||
xrandr_resources = NULL;
|
||||
}
|
||||
|
||||
if (arg != NULL) {
|
||||
XCloseDisplay((Display *) arg);
|
||||
arg = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&xrandr_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void *settings_thread_proc(void *arg) {
|
||||
Display *settings_disp = XOpenDisplay(XDisplayName(NULL));;
|
||||
if (settings_disp != NULL) {
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: %s\n",
|
||||
__FUNCTION__, __LINE__, "XOpenDisplay success.");
|
||||
|
||||
pthread_cleanup_push(settings_cleanup_proc, settings_disp);
|
||||
|
||||
int event_base = 0;
|
||||
int error_base = 0;
|
||||
if (XRRQueryExtension(settings_disp, &event_base, &error_base)) {
|
||||
Window root = XDefaultRootWindow(settings_disp);
|
||||
unsigned long event_mask = RRScreenChangeNotifyMask;
|
||||
XRRSelectInput(settings_disp, root, event_mask);
|
||||
|
||||
XEvent ev;
|
||||
|
||||
while(settings_disp != NULL) {
|
||||
XNextEvent(settings_disp, &ev);
|
||||
|
||||
if (ev.type == event_base + RRScreenChangeNotifyMask) {
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Received XRRScreenChangeNotifyEvent.\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
|
||||
pthread_mutex_lock(&xrandr_mutex);
|
||||
if (xrandr_resources != NULL) {
|
||||
XRRFreeScreenResources(xrandr_resources);
|
||||
}
|
||||
|
||||
xrandr_resources = XRRGetScreenResources(settings_disp, root);
|
||||
if (xrandr_resources == NULL) {
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: XRandR could not get screen resources!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
pthread_mutex_unlock(&xrandr_mutex);
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: XRandR is not currently available!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the thread cleanup handler.
|
||||
pthread_cleanup_pop(1);
|
||||
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: XOpenDisplay failure!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
IOHOOK_API screen_data* hook_create_screen_info(unsigned char *count) {
|
||||
*count = 0;
|
||||
screen_data *screens = NULL;
|
||||
|
||||
#if defined(USE_XINERAMA) && !defined(USE_XRANDR)
|
||||
if (XineramaIsActive(properties_disp)) {
|
||||
int xine_count = 0;
|
||||
XineramaScreenInfo *xine_info = XineramaQueryScreens(properties_disp, &xine_count);
|
||||
|
||||
if (xine_info != NULL) {
|
||||
if (xine_count > UINT8_MAX) {
|
||||
*count = UINT8_MAX;
|
||||
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: Screen count overflow detected!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
else {
|
||||
*count = (uint8_t) xine_count;
|
||||
}
|
||||
|
||||
screens = malloc(sizeof(screen_data) * xine_count);
|
||||
|
||||
if (screens != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < xine_count; i++) {
|
||||
screens[i] = (screen_data) {
|
||||
.number = xine_info[i].screen_number,
|
||||
.x = xine_info[i].x_org,
|
||||
.y = xine_info[i].y_org,
|
||||
.width = xine_info[i].width,
|
||||
.height = xine_info[i].height
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
XFree(xine_info);
|
||||
}
|
||||
}
|
||||
#elif defined(USE_XRANDR)
|
||||
pthread_mutex_lock(&xrandr_mutex);
|
||||
if (xrandr_resources != NULL) {
|
||||
int xrandr_count = xrandr_resources->ncrtc;
|
||||
if (xrandr_count > UINT8_MAX) {
|
||||
*count = UINT8_MAX;
|
||||
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: Screen count overflow detected!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
else {
|
||||
*count = (uint8_t) xrandr_count;
|
||||
}
|
||||
|
||||
screens = malloc(sizeof(screen_data) * xrandr_count);
|
||||
|
||||
if (screens != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < xrandr_count; i++) {
|
||||
XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(properties_disp, xrandr_resources, xrandr_resources->crtcs[i]);
|
||||
|
||||
if (crtc_info != NULL) {
|
||||
screens[i] = (screen_data) {
|
||||
.number = i + 1,
|
||||
.x = crtc_info->x,
|
||||
.y = crtc_info->y,
|
||||
.width = crtc_info->width,
|
||||
.height = crtc_info->height
|
||||
};
|
||||
|
||||
XRRFreeCrtcInfo(crtc_info);
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_WARN, "%s [%u]: XRandr failed to return crtc information! (%#X)\n",
|
||||
__FUNCTION__, __LINE__, xrandr_resources->crtcs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&xrandr_mutex);
|
||||
#else
|
||||
Screen* default_screen = DefaultScreenOfDisplay(properties_disp);
|
||||
|
||||
if (default_screen->width > 0 && default_screen->height > 0) {
|
||||
screens = malloc(sizeof(screen_data));
|
||||
|
||||
if (screens != NULL) {
|
||||
*count = 1;
|
||||
screens[0] = (screen_data) {
|
||||
.number = 1,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = default_screen->width,
|
||||
.height = default_screen->height
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return screens;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_auto_repeat_rate() {
|
||||
bool successful = false;
|
||||
long int value = -1;
|
||||
unsigned int delay = 0, rate = 0;
|
||||
|
||||
// Check and make sure we could connect to the x server.
|
||||
if (properties_disp != NULL) {
|
||||
#ifdef USE_XKB
|
||||
// Attempt to acquire the keyboard auto repeat rate using the XKB extension.
|
||||
if (!successful) {
|
||||
successful = XkbGetAutoRepeatRate(properties_disp, XkbUseCoreKbd, &delay, &rate);
|
||||
|
||||
if (successful) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: XkbGetAutoRepeatRate: %u.\n",
|
||||
__FUNCTION__, __LINE__, rate);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_XF86MISC
|
||||
// Fallback to the XF86 Misc extension if available and other efforts failed.
|
||||
if (!successful) {
|
||||
XF86MiscKbdSettings kb_info;
|
||||
successful = (bool) XF86MiscGetKbdSettings(properties_disp, &kb_info);
|
||||
if (successful) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: XF86MiscGetKbdSettings: %i.\n",
|
||||
__FUNCTION__, __LINE__, kbdinfo.rate);
|
||||
|
||||
delay = (unsigned int) kbdinfo.delay;
|
||||
rate = (unsigned int) kbdinfo.rate;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
|
||||
__FUNCTION__, __LINE__, "XOpenDisplay failure!");
|
||||
}
|
||||
|
||||
if (successful) {
|
||||
value = (long int) rate;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_auto_repeat_delay() {
|
||||
bool successful = false;
|
||||
long int value = -1;
|
||||
unsigned int delay = 0, rate = 0;
|
||||
|
||||
// Check and make sure we could connect to the x server.
|
||||
if (properties_disp != NULL) {
|
||||
#ifdef USE_XKB
|
||||
// Attempt to acquire the keyboard auto repeat rate using the XKB extension.
|
||||
if (!successful) {
|
||||
successful = XkbGetAutoRepeatRate(properties_disp, XkbUseCoreKbd, &delay, &rate);
|
||||
|
||||
if (successful) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: XkbGetAutoRepeatRate: %u.\n",
|
||||
__FUNCTION__, __LINE__, delay);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_XF86MISC
|
||||
// Fallback to the XF86 Misc extension if available and other efforts failed.
|
||||
if (!successful) {
|
||||
XF86MiscKbdSettings kb_info;
|
||||
successful = (bool) XF86MiscGetKbdSettings(properties_disp, &kb_info);
|
||||
if (successful) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: XF86MiscGetKbdSettings: %i.\n",
|
||||
__FUNCTION__, __LINE__, kbdinfo.delay);
|
||||
|
||||
delay = (unsigned int) kbdinfo.delay;
|
||||
rate = (unsigned int) kbdinfo.rate;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
|
||||
__FUNCTION__, __LINE__, "XOpenDisplay failure!");
|
||||
}
|
||||
|
||||
if (successful) {
|
||||
value = (long int) delay;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_pointer_acceleration_multiplier() {
|
||||
long int value = -1;
|
||||
int accel_numerator, accel_denominator, threshold;
|
||||
|
||||
// Check and make sure we could connect to the x server.
|
||||
if (properties_disp != NULL) {
|
||||
XGetPointerControl(properties_disp, &accel_numerator, &accel_denominator, &threshold);
|
||||
if (accel_denominator >= 0) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: XGetPointerControl: %i.\n",
|
||||
__FUNCTION__, __LINE__, accel_denominator);
|
||||
|
||||
value = (long int) accel_denominator;
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
|
||||
__FUNCTION__, __LINE__, "XOpenDisplay failure!");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_pointer_acceleration_threshold() {
|
||||
long int value = -1;
|
||||
int accel_numerator, accel_denominator, threshold;
|
||||
|
||||
// Check and make sure we could connect to the x server.
|
||||
if (properties_disp != NULL) {
|
||||
XGetPointerControl(properties_disp, &accel_numerator, &accel_denominator, &threshold);
|
||||
if (threshold >= 0) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: XGetPointerControl: %i.\n",
|
||||
__FUNCTION__, __LINE__, threshold);
|
||||
|
||||
value = (long int) threshold;
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
|
||||
__FUNCTION__, __LINE__, "XOpenDisplay failure!");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_pointer_sensitivity() {
|
||||
long int value = -1;
|
||||
int accel_numerator, accel_denominator, threshold;
|
||||
|
||||
// Check and make sure we could connect to the x server.
|
||||
if (properties_disp != NULL) {
|
||||
XGetPointerControl(properties_disp, &accel_numerator, &accel_denominator, &threshold);
|
||||
if (accel_numerator >= 0) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: XGetPointerControl: %i.\n",
|
||||
__FUNCTION__, __LINE__, accel_numerator);
|
||||
|
||||
value = (long int) accel_numerator;
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
|
||||
__FUNCTION__, __LINE__, "XOpenDisplay failure!");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
IOHOOK_API long int hook_get_multi_click_time() {
|
||||
long int value = 200;
|
||||
int click_time;
|
||||
bool successful = false;
|
||||
|
||||
#ifdef USE_XT
|
||||
// Check and make sure we could connect to the x server.
|
||||
if (xt_disp != NULL) {
|
||||
// Try and use the Xt extention to get the current multi-click.
|
||||
if (!successful) {
|
||||
// Fall back to the X Toolkit extension if available and other efforts failed.
|
||||
click_time = XtGetMultiClickTime(xt_disp);
|
||||
if (click_time >= 0) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: XtGetMultiClickTime: %i.\n",
|
||||
__FUNCTION__, __LINE__, click_time);
|
||||
|
||||
successful = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
|
||||
__FUNCTION__, __LINE__, "XOpenDisplay failure!");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check and make sure we could connect to the x server.
|
||||
if (properties_disp != NULL) {
|
||||
// Try and acquire the multi-click time from the user defined X defaults.
|
||||
if (!successful) {
|
||||
char *xprop = XGetDefault(properties_disp, "*", "multiClickTime");
|
||||
if (xprop != NULL && sscanf(xprop, "%4i", &click_time) != EOF) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: X default 'multiClickTime' property: %i.\n",
|
||||
__FUNCTION__, __LINE__, click_time);
|
||||
|
||||
successful = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!successful) {
|
||||
char *xprop = XGetDefault(properties_disp, "OpenWindows", "MultiClickTimeout");
|
||||
if (xprop != NULL && sscanf(xprop, "%4i", &click_time) != EOF) {
|
||||
logger(LOG_LEVEL_INFO, "%s [%u]: X default 'MultiClickTimeout' property: %i.\n",
|
||||
__FUNCTION__, __LINE__, click_time);
|
||||
|
||||
successful = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
|
||||
__FUNCTION__, __LINE__, "XOpenDisplay failure!");
|
||||
}
|
||||
|
||||
if (successful) {
|
||||
value = (long int) click_time;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Create a shared object constructor.
|
||||
__attribute__ ((constructor))
|
||||
void on_library_load() {
|
||||
// Make sure we are initialized for threading.
|
||||
XInitThreads();
|
||||
|
||||
// Open local display.
|
||||
properties_disp = XOpenDisplay(XDisplayName(NULL));
|
||||
if (properties_disp == NULL) {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
|
||||
__FUNCTION__, __LINE__, "XOpenDisplay failure!");
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: %s\n",
|
||||
__FUNCTION__, __LINE__, "XOpenDisplay success.");
|
||||
}
|
||||
|
||||
#ifdef USE_XRANDR
|
||||
// Create the thread attribute.
|
||||
pthread_attr_t settings_thread_attr;
|
||||
pthread_attr_init(&settings_thread_attr);
|
||||
|
||||
pthread_t settings_thread_id;
|
||||
if (pthread_create(&settings_thread_id, &settings_thread_attr, settings_thread_proc, NULL) == 0) {
|
||||
logger(LOG_LEVEL_DEBUG, "%s [%u]: Successfully created settings thread.\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
else {
|
||||
logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to create settings thread!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
// Make sure the thread attribute is removed.
|
||||
pthread_attr_destroy(&settings_thread_attr);
|
||||
#endif
|
||||
|
||||
#ifdef USE_XT
|
||||
XtToolkitInitialize();
|
||||
xt_context = XtCreateApplicationContext();
|
||||
|
||||
int argc = 0;
|
||||
char ** argv = { NULL };
|
||||
xt_disp = XtOpenDisplay(xt_context, NULL, "IOHook", "libIOhook", NULL, 0, &argc, argv);
|
||||
#endif
|
||||
|
||||
// Initialize.
|
||||
load_input_helper(properties_disp);
|
||||
}
|
||||
|
||||
// Create a shared object destructor.
|
||||
__attribute__ ((destructor))
|
||||
void on_library_unload() {
|
||||
// Disable the event hook.
|
||||
//hook_stop();
|
||||
|
||||
// Cleanup.
|
||||
unload_input_helper();
|
||||
|
||||
#ifdef USE_XT
|
||||
XtCloseDisplay(xt_disp);
|
||||
XtDestroyApplicationContext(xt_context);
|
||||
#endif
|
||||
|
||||
// Destroy the native displays.
|
||||
if (properties_disp != NULL) {
|
||||
XCloseDisplay(properties_disp);
|
||||
properties_disp = NULL;
|
||||
}
|
||||
}
|
1
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
1
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
@ -456,6 +456,7 @@ ccflags="$@"
|
||||
$2 ~ /^PERF_EVENT_IOC_/ ||
|
||||
$2 ~ /^SECCOMP_MODE_/ ||
|
||||
$2 ~ /^SPLICE_/ ||
|
||||
$2 ~ /^SYNC_FILE_RANGE_/ ||
|
||||
$2 !~ /^AUDIT_RECORD_MAGIC/ &&
|
||||
$2 !~ /IOC_MAGIC/ &&
|
||||
$2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ ||
|
||||
|
9
vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go
generated
vendored
@ -44,7 +44,6 @@ package unix
|
||||
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
||||
//sys Stat(path string, stat *Stat_t) (err error)
|
||||
//sys Statfs(path string, buf *Statfs_t) (err error)
|
||||
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) = SYS_SYNC_FILE_RANGE2
|
||||
//sys Truncate(path string, length int64) (err error)
|
||||
//sys Ustat(dev int, ubuf *Ustat_t) (err error)
|
||||
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
|
||||
@ -129,3 +128,11 @@ func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
//sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2
|
||||
|
||||
func SyncFileRange(fd int, off int64, n int64, flags int) error {
|
||||
// The sync_file_range and sync_file_range2 syscalls differ only in the
|
||||
// order of their arguments.
|
||||
return syncFileRange2(fd, flags, off, n)
|
||||
}
|
||||
|
212
vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
generated
vendored
Normal file
212
vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
generated
vendored
Normal file
@ -0,0 +1,212 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build riscv64,linux
|
||||
|
||||
package unix
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func EpollCreate(size int) (fd int, err error) {
|
||||
if size <= 0 {
|
||||
return -1, EINVAL
|
||||
}
|
||||
return EpollCreate1(0)
|
||||
}
|
||||
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
|
||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||
//sys Ftruncate(fd int, length int64) (err error)
|
||||
//sysnb Getegid() (egid int)
|
||||
//sysnb Geteuid() (euid int)
|
||||
//sysnb Getgid() (gid int)
|
||||
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Getuid() (uid int)
|
||||
//sys Listen(s int, n int) (err error)
|
||||
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
|
||||
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
|
||||
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
|
||||
|
||||
func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
|
||||
var ts *Timespec
|
||||
if timeout != nil {
|
||||
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
|
||||
}
|
||||
return Pselect(nfd, r, w, e, ts, nil)
|
||||
}
|
||||
|
||||
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
|
||||
//sys Setfsgid(gid int) (err error)
|
||||
//sys Setfsuid(uid int) (err error)
|
||||
//sysnb Setregid(rgid int, egid int) (err error)
|
||||
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
|
||||
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
|
||||
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Setreuid(ruid int, euid int) (err error)
|
||||
//sys Shutdown(fd int, how int) (err error)
|
||||
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
||||
|
||||
func Stat(path string, stat *Stat_t) (err error) {
|
||||
return Fstatat(AT_FDCWD, path, stat, 0)
|
||||
}
|
||||
|
||||
func Lchown(path string, uid int, gid int) (err error) {
|
||||
return Fchownat(AT_FDCWD, path, uid, gid, AT_SYMLINK_NOFOLLOW)
|
||||
}
|
||||
|
||||
func Lstat(path string, stat *Stat_t) (err error) {
|
||||
return Fstatat(AT_FDCWD, path, stat, AT_SYMLINK_NOFOLLOW)
|
||||
}
|
||||
|
||||
//sys Statfs(path string, buf *Statfs_t) (err error)
|
||||
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
|
||||
//sys Truncate(path string, length int64) (err error)
|
||||
|
||||
func Ustat(dev int, ubuf *Ustat_t) (err error) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
|
||||
//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
|
||||
//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
|
||||
//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
|
||||
//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
|
||||
//sysnb setgroups(n int, list *_Gid_t) (err error)
|
||||
//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
|
||||
//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
|
||||
//sysnb socket(domain int, typ int, proto int) (fd int, err error)
|
||||
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
|
||||
//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
|
||||
//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
|
||||
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
|
||||
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
|
||||
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
|
||||
|
||||
//sysnb Gettimeofday(tv *Timeval) (err error)
|
||||
|
||||
func setTimespec(sec, nsec int64) Timespec {
|
||||
return Timespec{Sec: sec, Nsec: nsec}
|
||||
}
|
||||
|
||||
func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: sec, Usec: usec}
|
||||
}
|
||||
|
||||
func futimesat(dirfd int, path string, tv *[2]Timeval) (err error) {
|
||||
if tv == nil {
|
||||
return utimensat(dirfd, path, nil, 0)
|
||||
}
|
||||
|
||||
ts := []Timespec{
|
||||
NsecToTimespec(TimevalToNsec(tv[0])),
|
||||
NsecToTimespec(TimevalToNsec(tv[1])),
|
||||
}
|
||||
return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
|
||||
}
|
||||
|
||||
func Time(t *Time_t) (Time_t, error) {
|
||||
var tv Timeval
|
||||
err := Gettimeofday(&tv)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if t != nil {
|
||||
*t = Time_t(tv.Sec)
|
||||
}
|
||||
return Time_t(tv.Sec), nil
|
||||
}
|
||||
|
||||
func Utime(path string, buf *Utimbuf) error {
|
||||
tv := []Timeval{
|
||||
{Sec: buf.Actime},
|
||||
{Sec: buf.Modtime},
|
||||
}
|
||||
return Utimes(path, tv)
|
||||
}
|
||||
|
||||
func utimes(path string, tv *[2]Timeval) (err error) {
|
||||
if tv == nil {
|
||||
return utimensat(AT_FDCWD, path, nil, 0)
|
||||
}
|
||||
|
||||
ts := []Timespec{
|
||||
NsecToTimespec(TimevalToNsec(tv[0])),
|
||||
NsecToTimespec(TimevalToNsec(tv[1])),
|
||||
}
|
||||
return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
|
||||
}
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, 0)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
func (r *PtraceRegs) PC() uint64 { return r.Pc }
|
||||
|
||||
func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc }
|
||||
|
||||
func (iov *Iovec) SetLen(length int) {
|
||||
iov.Len = uint64(length)
|
||||
}
|
||||
|
||||
func (msghdr *Msghdr) SetControllen(length int) {
|
||||
msghdr.Controllen = uint64(length)
|
||||
}
|
||||
|
||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
cmsg.Len = uint64(length)
|
||||
}
|
||||
|
||||
func InotifyInit() (fd int, err error) {
|
||||
return InotifyInit1(0)
|
||||
}
|
||||
|
||||
func Dup2(oldfd int, newfd int) (err error) {
|
||||
return Dup3(oldfd, newfd, 0)
|
||||
}
|
||||
|
||||
func Pause() (err error) {
|
||||
_, _, e1 := Syscall6(SYS_PPOLL, 0, 0, 0, 0, 0, 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
var ts *Timespec
|
||||
if timeout >= 0 {
|
||||
ts = new(Timespec)
|
||||
*ts = NsecToTimespec(int64(timeout) * 1e6)
|
||||
}
|
||||
if len(fds) == 0 {
|
||||
return ppoll(nil, 0, ts, nil)
|
||||
}
|
||||
return ppoll(&fds[0], len(fds), ts, nil)
|
||||
}
|
3
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
generated
vendored
@ -1891,6 +1891,9 @@ const (
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
3
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
generated
vendored
@ -1892,6 +1892,9 @@ const (
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
3
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
generated
vendored
@ -1898,6 +1898,9 @@ const (
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
3
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
generated
vendored
@ -1883,6 +1883,9 @@ const (
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SVE_MAGIC = 0x53564501
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
3
vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
generated
vendored
@ -1892,6 +1892,9 @@ const (
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
3
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
generated
vendored
@ -1892,6 +1892,9 @@ const (
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
3
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
generated
vendored
@ -1892,6 +1892,9 @@ const (
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
3
vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
generated
vendored
@ -1892,6 +1892,9 @@ const (
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
3
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
generated
vendored
@ -1947,6 +1947,9 @@ const (
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
3
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
generated
vendored
@ -1947,6 +1947,9 @@ const (
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
2625
vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
generated
vendored
Normal file
2625
vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
generated
vendored
3
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
generated
vendored
@ -1952,6 +1952,9 @@ const (
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
SYNC_FILE_RANGE_WRITE = 0x2
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
S_BLKSIZE = 0x200
|
||||
S_IEXEC = 0x40
|
||||
|
20
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
generated
vendored
20
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
generated
vendored
@ -1998,16 +1998,6 @@ func Statfs(path string, buf *Statfs_t) (err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
|
||||
_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 0, 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Truncate(path string, length int64) (err error) {
|
||||
var _p0 *byte
|
||||
_p0, err = BytePtrFromString(path)
|
||||
@ -2317,3 +2307,13 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func syncFileRange2(fd int, flags int, off int64, n int64) (err error) {
|
||||
_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
20
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
generated
vendored
20
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
generated
vendored
@ -1998,16 +1998,6 @@ func Statfs(path string, buf *Statfs_t) (err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
|
||||
_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 0, 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Truncate(path string, length int64) (err error) {
|
||||
var _p0 *byte
|
||||
_p0, err = BytePtrFromString(path)
|
||||
@ -2317,3 +2307,13 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func syncFileRange2(fd int, flags int, off int64, n int64) (err error) {
|
||||
_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
2114
vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go
generated
vendored
Normal file
2114
vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
286
vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
generated
vendored
Normal file
286
vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
generated
vendored
Normal file
@ -0,0 +1,286 @@
|
||||
// linux/mksysnum.pl -Wall -Werror -static -I/tmp/include /tmp/include/asm/unistd.h
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build riscv64,linux
|
||||
|
||||
package unix
|
||||
|
||||
const (
|
||||
SYS_IO_SETUP = 0
|
||||
SYS_IO_DESTROY = 1
|
||||
SYS_IO_SUBMIT = 2
|
||||
SYS_IO_CANCEL = 3
|
||||
SYS_IO_GETEVENTS = 4
|
||||
SYS_SETXATTR = 5
|
||||
SYS_LSETXATTR = 6
|
||||
SYS_FSETXATTR = 7
|
||||
SYS_GETXATTR = 8
|
||||
SYS_LGETXATTR = 9
|
||||
SYS_FGETXATTR = 10
|
||||
SYS_LISTXATTR = 11
|
||||
SYS_LLISTXATTR = 12
|
||||
SYS_FLISTXATTR = 13
|
||||
SYS_REMOVEXATTR = 14
|
||||
SYS_LREMOVEXATTR = 15
|
||||
SYS_FREMOVEXATTR = 16
|
||||
SYS_GETCWD = 17
|
||||
SYS_LOOKUP_DCOOKIE = 18
|
||||
SYS_EVENTFD2 = 19
|
||||
SYS_EPOLL_CREATE1 = 20
|
||||
SYS_EPOLL_CTL = 21
|
||||
SYS_EPOLL_PWAIT = 22
|
||||
SYS_DUP = 23
|
||||
SYS_DUP3 = 24
|
||||
SYS_FCNTL = 25
|
||||
SYS_INOTIFY_INIT1 = 26
|
||||
SYS_INOTIFY_ADD_WATCH = 27
|
||||
SYS_INOTIFY_RM_WATCH = 28
|
||||
SYS_IOCTL = 29
|
||||
SYS_IOPRIO_SET = 30
|
||||
SYS_IOPRIO_GET = 31
|
||||
SYS_FLOCK = 32
|
||||
SYS_MKNODAT = 33
|
||||
SYS_MKDIRAT = 34
|
||||
SYS_UNLINKAT = 35
|
||||
SYS_SYMLINKAT = 36
|
||||
SYS_LINKAT = 37
|
||||
SYS_UMOUNT2 = 39
|
||||
SYS_MOUNT = 40
|
||||
SYS_PIVOT_ROOT = 41
|
||||
SYS_NFSSERVCTL = 42
|
||||
SYS_STATFS = 43
|
||||
SYS_FSTATFS = 44
|
||||
SYS_TRUNCATE = 45
|
||||
SYS_FTRUNCATE = 46
|
||||
SYS_FALLOCATE = 47
|
||||
SYS_FACCESSAT = 48
|
||||
SYS_CHDIR = 49
|
||||
SYS_FCHDIR = 50
|
||||
SYS_CHROOT = 51
|
||||
SYS_FCHMOD = 52
|
||||
SYS_FCHMODAT = 53
|
||||
SYS_FCHOWNAT = 54
|
||||
SYS_FCHOWN = 55
|
||||
SYS_OPENAT = 56
|
||||
SYS_CLOSE = 57
|
||||
SYS_VHANGUP = 58
|
||||
SYS_PIPE2 = 59
|
||||
SYS_QUOTACTL = 60
|
||||
SYS_GETDENTS64 = 61
|
||||
SYS_LSEEK = 62
|
||||
SYS_READ = 63
|
||||
SYS_WRITE = 64
|
||||
SYS_READV = 65
|
||||
SYS_WRITEV = 66
|
||||
SYS_PREAD64 = 67
|
||||
SYS_PWRITE64 = 68
|
||||
SYS_PREADV = 69
|
||||
SYS_PWRITEV = 70
|
||||
SYS_SENDFILE = 71
|
||||
SYS_PSELECT6 = 72
|
||||
SYS_PPOLL = 73
|
||||
SYS_SIGNALFD4 = 74
|
||||
SYS_VMSPLICE = 75
|
||||
SYS_SPLICE = 76
|
||||
SYS_TEE = 77
|
||||
SYS_READLINKAT = 78
|
||||
SYS_FSTATAT = 79
|
||||
SYS_FSTAT = 80
|
||||
SYS_SYNC = 81
|
||||
SYS_FSYNC = 82
|
||||
SYS_FDATASYNC = 83
|
||||
SYS_SYNC_FILE_RANGE = 84
|
||||
SYS_TIMERFD_CREATE = 85
|
||||
SYS_TIMERFD_SETTIME = 86
|
||||
SYS_TIMERFD_GETTIME = 87
|
||||
SYS_UTIMENSAT = 88
|
||||
SYS_ACCT = 89
|
||||
SYS_CAPGET = 90
|
||||
SYS_CAPSET = 91
|
||||
SYS_PERSONALITY = 92
|
||||
SYS_EXIT = 93
|
||||
SYS_EXIT_GROUP = 94
|
||||
SYS_WAITID = 95
|
||||
SYS_SET_TID_ADDRESS = 96
|
||||
SYS_UNSHARE = 97
|
||||
SYS_FUTEX = 98
|
||||
SYS_SET_ROBUST_LIST = 99
|
||||
SYS_GET_ROBUST_LIST = 100
|
||||
SYS_NANOSLEEP = 101
|
||||
SYS_GETITIMER = 102
|
||||
SYS_SETITIMER = 103
|
||||
SYS_KEXEC_LOAD = 104
|
||||
SYS_INIT_MODULE = 105
|
||||
SYS_DELETE_MODULE = 106
|
||||
SYS_TIMER_CREATE = 107
|
||||
SYS_TIMER_GETTIME = 108
|
||||
SYS_TIMER_GETOVERRUN = 109
|
||||
SYS_TIMER_SETTIME = 110
|
||||
SYS_TIMER_DELETE = 111
|
||||
SYS_CLOCK_SETTIME = 112
|
||||
SYS_CLOCK_GETTIME = 113
|
||||
SYS_CLOCK_GETRES = 114
|
||||
SYS_CLOCK_NANOSLEEP = 115
|
||||
SYS_SYSLOG = 116
|
||||
SYS_PTRACE = 117
|
||||
SYS_SCHED_SETPARAM = 118
|
||||
SYS_SCHED_SETSCHEDULER = 119
|
||||
SYS_SCHED_GETSCHEDULER = 120
|
||||
SYS_SCHED_GETPARAM = 121
|
||||
SYS_SCHED_SETAFFINITY = 122
|
||||
SYS_SCHED_GETAFFINITY = 123
|
||||
SYS_SCHED_YIELD = 124
|
||||
SYS_SCHED_GET_PRIORITY_MAX = 125
|
||||
SYS_SCHED_GET_PRIORITY_MIN = 126
|
||||
SYS_SCHED_RR_GET_INTERVAL = 127
|
||||
SYS_RESTART_SYSCALL = 128
|
||||
SYS_KILL = 129
|
||||
SYS_TKILL = 130
|
||||
SYS_TGKILL = 131
|
||||
SYS_SIGALTSTACK = 132
|
||||
SYS_RT_SIGSUSPEND = 133
|
||||
SYS_RT_SIGACTION = 134
|
||||
SYS_RT_SIGPROCMASK = 135
|
||||
SYS_RT_SIGPENDING = 136
|
||||
SYS_RT_SIGTIMEDWAIT = 137
|
||||
SYS_RT_SIGQUEUEINFO = 138
|
||||
SYS_RT_SIGRETURN = 139
|
||||
SYS_SETPRIORITY = 140
|
||||
SYS_GETPRIORITY = 141
|
||||
SYS_REBOOT = 142
|
||||
SYS_SETREGID = 143
|
||||
SYS_SETGID = 144
|
||||
SYS_SETREUID = 145
|
||||
SYS_SETUID = 146
|
||||
SYS_SETRESUID = 147
|
||||
SYS_GETRESUID = 148
|
||||
SYS_SETRESGID = 149
|
||||
SYS_GETRESGID = 150
|
||||
SYS_SETFSUID = 151
|
||||
SYS_SETFSGID = 152
|
||||
SYS_TIMES = 153
|
||||
SYS_SETPGID = 154
|
||||
SYS_GETPGID = 155
|
||||
SYS_GETSID = 156
|
||||
SYS_SETSID = 157
|
||||
SYS_GETGROUPS = 158
|
||||
SYS_SETGROUPS = 159
|
||||
SYS_UNAME = 160
|
||||
SYS_SETHOSTNAME = 161
|
||||
SYS_SETDOMAINNAME = 162
|
||||
SYS_GETRLIMIT = 163
|
||||
SYS_SETRLIMIT = 164
|
||||
SYS_GETRUSAGE = 165
|
||||
SYS_UMASK = 166
|
||||
SYS_PRCTL = 167
|
||||
SYS_GETCPU = 168
|
||||
SYS_GETTIMEOFDAY = 169
|
||||
SYS_SETTIMEOFDAY = 170
|
||||
SYS_ADJTIMEX = 171
|
||||
SYS_GETPID = 172
|
||||
SYS_GETPPID = 173
|
||||
SYS_GETUID = 174
|
||||
SYS_GETEUID = 175
|
||||
SYS_GETGID = 176
|
||||
SYS_GETEGID = 177
|
||||
SYS_GETTID = 178
|
||||
SYS_SYSINFO = 179
|
||||
SYS_MQ_OPEN = 180
|
||||
SYS_MQ_UNLINK = 181
|
||||
SYS_MQ_TIMEDSEND = 182
|
||||
SYS_MQ_TIMEDRECEIVE = 183
|
||||
SYS_MQ_NOTIFY = 184
|
||||
SYS_MQ_GETSETATTR = 185
|
||||
SYS_MSGGET = 186
|
||||
SYS_MSGCTL = 187
|
||||
SYS_MSGRCV = 188
|
||||
SYS_MSGSND = 189
|
||||
SYS_SEMGET = 190
|
||||
SYS_SEMCTL = 191
|
||||
SYS_SEMTIMEDOP = 192
|
||||
SYS_SEMOP = 193
|
||||
SYS_SHMGET = 194
|
||||
SYS_SHMCTL = 195
|
||||
SYS_SHMAT = 196
|
||||
SYS_SHMDT = 197
|
||||
SYS_SOCKET = 198
|
||||
SYS_SOCKETPAIR = 199
|
||||
SYS_BIND = 200
|
||||
SYS_LISTEN = 201
|
||||
SYS_ACCEPT = 202
|
||||
SYS_CONNECT = 203
|
||||
SYS_GETSOCKNAME = 204
|
||||
SYS_GETPEERNAME = 205
|
||||
SYS_SENDTO = 206
|
||||
SYS_RECVFROM = 207
|
||||
SYS_SETSOCKOPT = 208
|
||||
SYS_GETSOCKOPT = 209
|
||||
SYS_SHUTDOWN = 210
|
||||
SYS_SENDMSG = 211
|
||||
SYS_RECVMSG = 212
|
||||
SYS_READAHEAD = 213
|
||||
SYS_BRK = 214
|
||||
SYS_MUNMAP = 215
|
||||
SYS_MREMAP = 216
|
||||
SYS_ADD_KEY = 217
|
||||
SYS_REQUEST_KEY = 218
|
||||
SYS_KEYCTL = 219
|
||||
SYS_CLONE = 220
|
||||
SYS_EXECVE = 221
|
||||
SYS_MMAP = 222
|
||||
SYS_FADVISE64 = 223
|
||||
SYS_SWAPON = 224
|
||||
SYS_SWAPOFF = 225
|
||||
SYS_MPROTECT = 226
|
||||
SYS_MSYNC = 227
|
||||
SYS_MLOCK = 228
|
||||
SYS_MUNLOCK = 229
|
||||
SYS_MLOCKALL = 230
|
||||
SYS_MUNLOCKALL = 231
|
||||
SYS_MINCORE = 232
|
||||
SYS_MADVISE = 233
|
||||
SYS_REMAP_FILE_PAGES = 234
|
||||
SYS_MBIND = 235
|
||||
SYS_GET_MEMPOLICY = 236
|
||||
SYS_SET_MEMPOLICY = 237
|
||||
SYS_MIGRATE_PAGES = 238
|
||||
SYS_MOVE_PAGES = 239
|
||||
SYS_RT_TGSIGQUEUEINFO = 240
|
||||
SYS_PERF_EVENT_OPEN = 241
|
||||
SYS_ACCEPT4 = 242
|
||||
SYS_RECVMMSG = 243
|
||||
SYS_ARCH_SPECIFIC_SYSCALL = 244
|
||||
SYS_WAIT4 = 260
|
||||
SYS_PRLIMIT64 = 261
|
||||
SYS_FANOTIFY_INIT = 262
|
||||
SYS_FANOTIFY_MARK = 263
|
||||
SYS_NAME_TO_HANDLE_AT = 264
|
||||
SYS_OPEN_BY_HANDLE_AT = 265
|
||||
SYS_CLOCK_ADJTIME = 266
|
||||
SYS_SYNCFS = 267
|
||||
SYS_SETNS = 268
|
||||
SYS_SENDMMSG = 269
|
||||
SYS_PROCESS_VM_READV = 270
|
||||
SYS_PROCESS_VM_WRITEV = 271
|
||||
SYS_KCMP = 272
|
||||
SYS_FINIT_MODULE = 273
|
||||
SYS_SCHED_SETATTR = 274
|
||||
SYS_SCHED_GETATTR = 275
|
||||
SYS_RENAMEAT2 = 276
|
||||
SYS_SECCOMP = 277
|
||||
SYS_GETRANDOM = 278
|
||||
SYS_MEMFD_CREATE = 279
|
||||
SYS_BPF = 280
|
||||
SYS_EXECVEAT = 281
|
||||
SYS_USERFAULTFD = 282
|
||||
SYS_MEMBARRIER = 283
|
||||
SYS_MLOCK2 = 284
|
||||
SYS_COPY_FILE_RANGE = 285
|
||||
SYS_PREADV2 = 286
|
||||
SYS_PWRITEV2 = 287
|
||||
SYS_PKEY_MPROTECT = 288
|
||||
SYS_PKEY_ALLOC = 289
|
||||
SYS_PKEY_FREE = 290
|
||||
SYS_STATX = 291
|
||||
SYS_IO_PGETEVENTS = 292
|
||||
)
|
7
vendor/golang.org/x/sys/unix/ztypes_linux_386.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_386.go
generated
vendored
@ -510,6 +510,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
7
vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
generated
vendored
@ -514,6 +514,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
7
vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
generated
vendored
@ -513,6 +513,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
7
vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
generated
vendored
@ -515,6 +515,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
7
vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
generated
vendored
@ -511,6 +511,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
7
vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
generated
vendored
@ -515,6 +515,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
7
vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
generated
vendored
@ -515,6 +515,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
7
vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
generated
vendored
@ -511,6 +511,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
7
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
generated
vendored
@ -516,6 +516,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
7
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
generated
vendored
@ -516,6 +516,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
1919
vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
generated
vendored
Normal file
1919
vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
generated
vendored
@ -514,6 +514,13 @@ const (
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTN_UNSPEC = 0x0
|
||||
RTN_UNICAST = 0x1
|
||||
RTN_LOCAL = 0x2
|
||||
|
58
vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
58
vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
@ -655,7 +655,7 @@ type RawSockaddr struct {
|
||||
|
||||
type RawSockaddrAny struct {
|
||||
Addr RawSockaddr
|
||||
Pad [96]int8
|
||||
Pad [100]int8
|
||||
}
|
||||
|
||||
type Sockaddr interface {
|
||||
@ -704,19 +704,69 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
|
||||
return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
|
||||
}
|
||||
|
||||
type RawSockaddrUnix struct {
|
||||
Family uint16
|
||||
Path [UNIX_PATH_MAX]int8
|
||||
}
|
||||
|
||||
type SockaddrUnix struct {
|
||||
Name string
|
||||
raw RawSockaddrUnix
|
||||
}
|
||||
|
||||
func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
|
||||
// TODO(brainman): implement SockaddrUnix.sockaddr()
|
||||
return nil, 0, syscall.EWINDOWS
|
||||
name := sa.Name
|
||||
n := len(name)
|
||||
if n > len(sa.raw.Path) {
|
||||
return nil, 0, syscall.EINVAL
|
||||
}
|
||||
if n == len(sa.raw.Path) && name[0] != '@' {
|
||||
return nil, 0, syscall.EINVAL
|
||||
}
|
||||
sa.raw.Family = AF_UNIX
|
||||
for i := 0; i < n; i++ {
|
||||
sa.raw.Path[i] = int8(name[i])
|
||||
}
|
||||
// length is family (uint16), name, NUL.
|
||||
sl := int32(2)
|
||||
if n > 0 {
|
||||
sl += int32(n) + 1
|
||||
}
|
||||
if sa.raw.Path[0] == '@' {
|
||||
sa.raw.Path[0] = 0
|
||||
// Don't count trailing NUL for abstract address.
|
||||
sl--
|
||||
}
|
||||
|
||||
return unsafe.Pointer(&sa.raw), sl, nil
|
||||
}
|
||||
|
||||
func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
|
||||
switch rsa.Addr.Family {
|
||||
case AF_UNIX:
|
||||
return nil, syscall.EWINDOWS
|
||||
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
|
||||
sa := new(SockaddrUnix)
|
||||
if pp.Path[0] == 0 {
|
||||
// "Abstract" Unix domain socket.
|
||||
// Rewrite leading NUL as @ for textual display.
|
||||
// (This is the standard convention.)
|
||||
// Not friendly to overwrite in place,
|
||||
// but the callers below don't care.
|
||||
pp.Path[0] = '@'
|
||||
}
|
||||
|
||||
// Assume path ends at NUL.
|
||||
// This is not technically the Linux semantics for
|
||||
// abstract Unix domain sockets--they are supposed
|
||||
// to be uninterpreted fixed-size binary blobs--but
|
||||
// everyone uses this convention.
|
||||
n := 0
|
||||
for n < len(pp.Path) && pp.Path[n] != 0 {
|
||||
n++
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
|
||||
sa.Name = string(bytes)
|
||||
return sa, nil
|
||||
|
||||
case AF_INET:
|
||||
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
|
||||
|
4
vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
4
vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
@ -1453,7 +1453,7 @@ type SmallRect struct {
|
||||
Bottom int16
|
||||
}
|
||||
|
||||
// Used with GetConsoleScreenBuffer to retreive information about a console
|
||||
// Used with GetConsoleScreenBuffer to retrieve information about a console
|
||||
// screen buffer. See
|
||||
// https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str
|
||||
// for details.
|
||||
@ -1465,3 +1465,5 @@ type ConsoleScreenBufferInfo struct {
|
||||
Window SmallRect
|
||||
MaximumWindowSize Coord
|
||||
}
|
||||
|
||||
const UNIX_PATH_MAX = 108 // defined in afunix.h
|
||||
|
Loading…
Reference in New Issue
Block a user