Showing preview only (280K chars total). Download the full file or copy to clipboard to get everything.
Repository: p2rkw/xf86-input-mtrack
Branch: master
Commit: d38088b43306
Files: 44
Total size: 267.0 KB
Directory structure:
gitextract_jeyfc4m8/
├── .gitignore
├── COPYING
├── CREDITS
├── Makefile.am
├── README.md
├── RELEASE.md
├── configure.ac
├── debian/
│ ├── README.Debian
│ ├── changelog
│ ├── compat
│ ├── control
│ ├── copyright
│ ├── dirs
│ └── rules
├── driver/
│ ├── mprops.c
│ └── mtrack.c
├── examples/
│ ├── acer-aspire-s3.conf
│ ├── asus-zenbook-ux330ua-ah55
│ ├── dell-precision-5520.conf
│ ├── dell-xps13-9333.conf
│ ├── lenovo-710s.conf
│ ├── lenovo-yoga-2-pro.conf
│ ├── macbook-pro-retina-2013.conf
│ └── macbook.conf
├── include/
│ ├── button.h
│ ├── capabilities.h
│ ├── common.h
│ ├── gestures.h
│ ├── hwstate.h
│ ├── mconfig.h
│ ├── mprops.h
│ ├── mtouch.h
│ ├── mtstate.h
│ └── trig.h
├── required_packages.txt
├── src/
│ ├── capabilities.c
│ ├── gestures.c
│ ├── hwstate.c
│ ├── mconfig.c
│ ├── mtouch.c
│ ├── mtstate.c
│ └── trig.c
└── tools/
├── mtrack-test.c
└── reconfigure-xinput.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.o
*.lo
*.la
*.swp
*.dirstamp
.deps/
.libs/
Makefile
Makefile.in
/m4
/missing
/libtool
install-sh
ltmain.sh
/aclocal.m4
/autom4te.cache/
/build-aux/
/config.*
/configure
/stamp-h1
/depcomp
/compile
debian/files
debian/xserver-xorg-input-mtrack.debhelper.log
debian/xserver-xorg-input-mtrack.substvars
debian/xserver-xorg-input-mtrack/
mtrack-test
================================================
FILE: COPYING
================================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) 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
this service 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 make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. 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.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
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
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the 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 a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE 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.
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
convey 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 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision 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, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This 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 Library General
Public License instead of this License.
================================================
FILE: CREDITS
================================================
This is a copy of the CREDITS file from the xf86-input-multitouch driver.
---
Multitouch X driver (GPL license)
Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
---
The Multitouch X driver extracts a lot of X knowledge from the
synaptics X driver (MIT license)
Copyright (C) 1997 C. Scott Ananian
Copyright (C) 1998-2000 Bruce Kalk
Copyright (C) 1999 Henry Davies
Copyright (C) 2001 Stefan Gmeiner
Copyright (C) 2002 Linuxcare Inc. David Kennedy
Copyright (C) 2003 Fred Hucht
Copyright (C) 2003 Neil Brown
Copyright (C) 2003 Jörg Bösner
Copyright (C) 2003 Hartwig Felger
Copyright (C) 2002-2007 Peter Osterlund
Copyright (C) 2004 Arne Schwabe
Copyright (C) 2004 Matthias Ihmig
Copyright (C) 2004 Alexei Gilchrist
Copyright (C) 2006-2007 Christian Thaeter
Copyright (C) 2006 Stefan Bethge
Copyright (C) 2007 Joseph P. Skudlarek
Copyright (C) 2007 Florian Loitsch
Copyright (C) 2008 Fedor P. Goncharov
Copyright (C) 2008-2009 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---
================================================
FILE: Makefile.am
================================================
SOURCES_COMMON = \
src/capabilities.c \
src/gestures.c \
src/hwstate.c \
src/mconfig.c \
src/mtouch.c \
src/mtstate.c \
src/trig.c
@DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
@DRIVER_NAME@_drv_la_SOURCES = $(SOURCES_COMMON) \
driver/mtrack.c \
driver/mprops.c
@DRIVER_NAME@_drv_ladir = @inputdir@
noinst_PROGRAMS = mtrack-test
mtrack_test_SOURCES = $(SOURCES_COMMON) \
tools/mtrack-test.c
mtrack_test_CFLAGS = $(AM_CFLAGS)
ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -I$(top_srcdir)/include/ \
-I/usr/include/xorg \
-I/usr/include/pixman-1
AM_CFLAGS = $(XORG_CFLAGS)
.PHONY: ChangeLog INSTALL
INSTALL:
$(INSTALL_CMD)
ChangeLog:
$(CHANGELOG_CMD)
dist-hook: ChangeLog INSTALL
================================================
FILE: README.md
================================================
xf86-input-mtrack
=================
###### v0.5.1
An Xorg driver for multitouch trackpads. Supports any trackpad whose kernel
driver uses the slotted multitouch protocol. For more information on the
protocol see the [kernel documentation][1].
This driver is compatible with Xorg server versions 1.7 to 1.19.0 It requires
the [mtdev][4] library to operate.
## License
* Copyright (C) 2015-2018 Paweł Turkowski <p2rkw0@gmail.com>
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
This software is licensed under the [GPLv2][2] and is a fork of the
[xf86-input-multitouch][3] driver by Henrik Rydberg.
## Building and Installing
This is a standard autoconf package. So:
```
./configure
make && make install
```
It is likely that you will need to change system-dependent paths such as the
xorg module directory. Otherwise mtrack may be not installed in xserver search
path.
See `configure --help` for options.
On Debian systems (including Ubuntu) you may also need to install the `xorg-dev`
package prior to these commands.
To build deb package and install in system wide you will usually have to change
installation prefix to /usr like so:
```
./configure --prefix=/usr
dpkg-buildpackage
```
## Bug Reporting
If you found a bug, and you are going to submit it, first run
```
xinput --list
```
then find your touchpad name/ID on the list and create report with output of
```
xinput --list-props <your touchpad ID>
```
attached.
## Configuration
The following is a minimal working InputClass section for xorg.conf:
```
Section "InputClass"
MatchIsTouchpad "on"
Identifier "Touchpads"
Driver "mtrack"
# In case of problems enable/disable this line:
MatchDevicePath "/dev/input/event*"
EndSection
```
---
To apply changes made in xorg.conf (or related files) X server have to be restarted.
Changes made with `xinput` are applied immedietly but they are not saved between sessions.
### Options
Configuration options may be defined inside the InputClass section to configure
the driver. See examples/ directory for example configuration files. Feel free to submit
yours, named as your laptop's model.
Available options and their defaults are as follows.
---
#### Basic
**[TrackpadDisable](#TrackpadDisable)**<a name="TrackpadDisable"></a>
Disables trackpad touch input. A value of 0 will enable the trackpad. A value
of 1 will disable tapping and gestures but not movement. A value of 2 will
disable all input. A value of 3 will also disable physical buttons.
Integer. Default is 0.
**[ButtonEnable](#ButtonEnable)**<a name="ButtonEnable"></a>
Whether or not to enable the physical buttons on or near the trackpad.
Boolean value. Defaults to true.
**[ButtonIntegrated](#ButtonIntegrated)**<a name="ButtonIntegrated"></a>
Whether or not the physical buttons are integrated with the trackpad. If you
have a one-piece trackpad like on newer MacBooks, this should be set to true.
Button emulation depends on this value being correct.
Boolean value. Defaults to true.
---
#### Responsiveness
**[Sensitivity](#Sensitivity)**<a name="Sensitivity"></a>
Adjusts the sensitivity (movement speed) of the touchpad. This is a real number
greater than or equal to zero. A value of 0 will disable pointer movement.
Float value. Default is 1.
**[FingerHigh](#FingerHigh)**<a name="FingerHigh"></a>
Defines the pressure at which a finger is detected as a touch. This is a
percentage represented as an integer.
Integer value. Default is 5.
**[FingerLow](#FingerLow)**<a name="FingerLow"></a>
Defines the pressure at which a finger is detected as a release. This is a
percentage represented as an integer.
Integer value. Default is 5.
**[IgnoreThumb](#IgnoreThumb)**<a name="IgnoreThumb"></a>
Whether or not to ignore touches that are determined to be thumbs.
Boolean value. Defaults to false.
**[IgnorePalm](#IgnorePalm)**<a name="IgnorePalm"></a>
Whether or not to ignore touches that are determined to be palms.
Boolean value. Defaults to false.
**[DisableOnThumb](#DisableOnThumb)**<a name="DisableOnThumb"></a>
Whether or not to disable the entire trackpad when a thumb is touching.
Boolean value. Defaults to false.
**[DisableOnPalm](#DisableOnPalm)**<a name="DisableOnPalm"></a>
Whether or not to disable the entire trackpad when a palm is touching.
Boolean value. Defaults to false.
**[ThumbSize](#ThumbSize)**<a name="ThumbSize"></a>
The minimum size of what's considered a thumb. It is expected that a thumb
will be larger than other fingers. This is represented as a percentage of the
maximum touch value and is dependent on the trackpad hardware.
Integer value. Defaults to 25.
**[PalmSize](#PalmSize)**<a name="PalmSize"></a>
The minimum size of what's considered a palm. Palms are expected to be very
large on the trackpad. This is represented as a percentage of the maximum touch
value and is dependent on the trackpad hardware.
Integer value. Defaults to 40.
**[ThumbRatio](#ThumbRatio)**<a name="ThumbRatio"></a>
The width/length ratio of what's considered a thumb. It is expected that a
thumb is longer than it is wide. This tells the driver how much longer.
Percentage represented by an integer.
Integer value. Defaults to 70.
---
#### Zones<a name="Zones"></a>
Divide the touchpad into "zones". Clicking the integrated button in one of
these zones will send the button event configured for each {First, Second, Third}ZoneButton.
The driver will only add zones for the ZoneButton values that
are enabled. The zone splitting start from the left to right using the first to third value.
So enabling only SecondZoneButton and ThirdZoneButton will create two
zones, the left-middle part will fire SecondZoneButton and the middle-right part ThirdZoneButton.
**[ButtonZonesEnable](#ButtonZonesEnable)**<a name="ButtonZonesEnable"></a>
Whether or not to enable button zones. If button zones are enabled then the
trackpad will be split into one, two, or three vertical zones.
Boolean value. Defaults to false.
**[FirstZoneButton](#FirstZoneButton)**<a name="FirstZoneButton"></a>
The button to emulate when the zone is pressed. This is the leftmost part of the pad.
Integer value. A value of 0 disables this zone split.
Integer value. Defaults to 1.
**[SecondZoneButton](#SecondZoneButton)**<a name="SecondZoneButton"></a>
The button to emulate when the zone is pressed. This will float to the right of
the leftmost zone. Integer value. A value of 0 disables this zone split.
Integer value. Defaults to 2.
**[ThirdZoneButton](#ThirdZoneButton)**<a name="ThirdZoneButton"></a>
The button to emulate when the zone is pressed. This will float to the right of
the leftmost zone. Integer value. A value of 0 disables this zone split.
Integer value. Defaults to 0.
**[LimitButtonZonesToBottomEdge](#LimitButtonZonesToBottomEdge)**<a name="LimitButtonZonesToBottomEdge"></a>
Restrict button zones inside the [EdgeBottom](#EdgeBottomSize) area. So instead of enabling zones
on the full pad height, the zone is limited to the percentage set for the [EdgeBottom](#EdgeBottomSize).
Boolean value. Default to false.
---
#### Physical click
**[ClickFinger0](#ClickFinger0)**<a name="ClickFinger0"></a>
Which button to emulate when no valid finger placement is touching the trackpad during a
click, as on "EdgeBottom".
Integer value. A value of 0 disables one-touch emulation. Defaults to 0.
**[ClickFinger1](#ClickFinger1)**<a name="ClickFinger1"></a>
Which button to emulate when one finger is touching the trackpad during a
click.
Integer value. A value of 0 disables one-touch emulation. Defaults to 1.
**[ClickFinger2](#ClickFinger2)**<a name="ClickFinger2"></a>
Which button to emulate when two fingers are touching the trackpad during a
click.
Integer value. A value of 0 disabled one-touch emulation. Defaults to 2.
**[ClickFinger3](#ClickFinger3)**<a name="ClickFinger3"></a>
Which button to emulate when three fingers are touching the trackpad during a
click.
Integer value. A value of 0 disabled one-touch emulation. Defaults to 3.
**[ButtonMoveEmulate](#ButtonMoveEmulate)**<a name="ButtonMoveEmulate"></a>
Whether or not to count the moving finger when emulating button clicks.
Useful to disable if you use two hands on trackpad.
Boolean value. Defaults to true.
**[ButtonTouchExpire](#ButtonTouchExpire)**<a name="ButtonTouchExpire"></a>
How long (in ms) to consider a touching finger as part of button emulation. A
value of 0 will not expire touches.
Integer value. Defaults to 100.
---
#### Tap clicking
**[TapButton1](#TapButton1)**<a name="TapButton1"></a>
Which button to emulate for one-finger tapping. Integer value. A value of 0
disables one-finger tapping.
Integer value. Defaults to 1.
**[TapButton2](#TapButton2)**<a name="TapButton2"></a>
Which button to emulate for two-finger tapping. Integer value. A value of 0
disables two-finger tapping.
Integer value. Defaults to 3.
**[TapButton3](#TapButton3)**<a name="TapButton3"></a>
Which button to emulate for three-finger tapping. Integer value. A value of 0
disables three-finger tapping.
Integer value. Defaults to 2.
**[TapButton4](#TapButton4)**<a name="TapButton4"></a>
Which button to emulate for four-finger tapping. Integer value. A value of 0
disables three-finger tapping.
Integer value. Defaults to 0.
**[ClickTime](#ClickTime)**<a name="ClickTime"></a>
When tapping, how much time to hold down the emulated button.
Integer value representing milliseconds. Defaults to 50.
**[MaxTapTime](#MaxTapTime)**<a name="MaxTapTime"></a>
The amount of time to wait for incoming touches after first one before counting
it as emulated button click.
Integer value representing milliseconds. Defaults to 120.
**[MaxTapMove](#MaxTapMove)**<a name="MaxTapMove"></a>
How far a touch is allowed to move before counting it is no longer considered a
tap.
Integer value. Defaults to 400.
#### Gesture
---
##### Basic
**[GestureClickTime](#GestureClickTime)**<a name="GestureClickTime"></a>
When a gesture triggers a click, how much time to hold down the emulated button.
Integer value representing milliseconds. Defaults to 10.
**[GestureWaitTime](#GestureWaitTime)**<a name="GestureWaitTime"></a>
Touches are allowed to transition from one gesture to another. For example, you
may go from scrolling to swiping without releasing your fingers from the pad.
This value is the amount of time you must be performing the new gesture before
it is triggered. This prevents accidental touches from triggering other
gestures.
Integer value representing milliseconds. Defaults to 100.
---
##### Two fingers Scrolling<a name="two-finger-scrolling"></a>
**[ScrollDistance](#ScrollDistance)**<a name="ScrollDistance"></a>
For two finger scrolling. This sets the speed of your scrolling: the lower the
number, the faster you scroll.
Technically, it is how far you must move your fingers before a button
click registering scrolling is triggered.
Integer value. Defaults to 150.
**[ScrollClickTime](#ScrollClickTime)**<a name="ScrollClickTime"></a>
For two finger scrolling. How long button triggered by scrolling
will be hold down. A value of 0 will hold button down till end of gesture.
0 - emit button click only once pre "instance" of gesture.
Integer value representing milliseconds.
Integer value. Defaults to 20.
**[ScrollSensitivity](#ScrollSensitivity)**<a name="ScrollSensitivity"></a>
For two finger scrolling. Sensitivity (movement speed) of pointer during two
finger scrolling. A value of 0 disables pointer movement during gesture.
Integer value expressed as parts per thousand of normal sensivity.
A value of 1000 results with normal movement speed.
Integer value. Defaults to 0.
**[ScrollUpButton](#ScrollUpButton)**<a name="ScrollUpButton"></a>
For two finger scrolling. The button that is triggered by scrolling up.
Integer value. A value of 0 disables scrolling up. Defaults to 4.
**[ScrollDownButton](#ScrollDownButton)**<a name="ScrollDownButton"></a>
For two finger scrolling. The button that is triggered by scrolling down.
Integer value. A value of 0 disables scrolling down. Defaults to 5.
**[ScrollLeftButton](#ScrollLeftButton)**<a name="ScrollLeftButton"></a>
For two finger scrolling. The button that is triggered by scrolling left.
Integer value. A value of 0 disables scrolling left. Defaults to 6.
**[ScrollRightButton](#ScrollRightButton)**<a name="ScrollRightButton"></a>
For two finger scrolling. The button that is triggered by scrolling right.
Integer value. A value of 0 disables scrolling right. Defaults to 7.
**[ScrollSmooth](#ScrollSmooth)**<a name="ScrollSmooth"></a>
For two finger scrolling. Whether to generate high precision scroll events.
Boolean value. Defaults to 1.
Property: "Trackpad High Smooth Scroll"
**[ScrollCoastDuration](#ScrollCoastDuration)**<a name="ScrollCoastDuration"></a>
How long after finished scrolling movement should be continued. Works only
with smooth scrolling enabled.
Floating value representing miliseconds. Defaults to 200.0.
Property: "Trackpad Scroll Coasting"
**[ScrollCoastEnableSpeed](#ScrollCoastEnableSpeed)**<a name="ScrollCoastEnableSpeed"></a>
How fast scroll should be to enable coasting feature.
Floating value. Defaults to 0.1.
Property: "Trackpad Scroll Coasting"
**[ScrollCoastNoBoost](#ScrollCoastNoBoost)**<a name="ScrollCoastNoBoost"></a>
Disable boosting on second scroll gesture during coasting
Boolean value. Defaults to false.
Property: "Trackpad Scroll Coasting"
**[ScrollCoastEase](#ScrollCoastEase)**<a name="ScrollCoastEase"></a>
Apply easing effect on coasting
Boolean value. Defaults to false.
Property: "Trackpad Scroll Coasting"
---
##### Three fingers swipe<a name="three-finger-swipe"></a>
**[SwipeDistance](#SwipeDistance)**<a name="SwipeDistance"></a>
For three finger swiping. How far you must move your fingers before a button
click is triggered.
Integer value. Defaults to 700.
**[SwipeClickTime](#SwipeClickTime)**<a name="SwipeClickTime"></a>
For three finger swiping. How long button triggered by swiping
will be hold down.
Integer value representing milliseconds. Defaults to 300.
**[SwipeSensitivity](#SwipeSensitivity)**<a name="SwipeSensitivity"></a>
For three finger scrolling. Sensitivity (movement speed) of pointer during three
finger scrolling. A value of 0 disables pointer movement during gesture.
Integer value expressed as parts per thousand of normal sensivity.
A value of 1000 results with normal movement speed. Defaults to 0.
**[SwipeUpButton](#SwipeUpButton)**<a name="SwipeUpButton"></a>
For three finger swiping. The button that is triggered by swiping up.
Integer value. A value of 0 disables swiping up. Defaults to 8.
**[SwipeDownButton](#SwipeDownButton)**<a name="SwipeDownButton"></a>
For three finger swiping. The button that is triggered by swiping down.
Integer value. A value of 0 disables swiping down. Defaults to 9.
**[SwipeLeftButton](#SwipeLeftButton)**<a name="SwipeLeftButton"></a>
For three finger swiping. The button that is triggered by swiping left.
Integer value. A value of 0 disables swiping left. Defaults to 10.
**[SwipeRightButton](#SwipeRightButton)**<a name="SwipeRightButton"></a>
For three finger swiping. The button that is triggered by swiping right.
Integer value. A value of 0 disables swiping right. Defaults to 11.
---
##### Four fingers swipe<a name="four-finger-swipe"></a>
**[Swipe4Distance](#Swipe4Distance)**<a name="Swipe4Distance"></a>
For four finger swiping. How far you must move your fingers before a button
click is triggered.
Integer value. Defaults to 700.
**[Swipe4ClickTime](#Swipe4ClickTime)**<a name="Swipe4ClickTime"></a>
For four finger swiping. How long button triggered by swiping
will be hold down.
Integer value representing milliseconds. Defaults to 300.
**[Swipe4Sensitivity](#Swipe4Sensitivity)**<a name="Swipe4Sensitivity"></a>
For four finger scrolling. Sensitivity (movement speed) of pointer during four
finger scrolling. A value of 0 disables pointer movement during gesture.
Integer value expressed as parts per thousand of normal sensivity.
A value of 1000 results with normal movement speed. Defaults to 0.
**[Swipe4UpButton](#Swipe4UpButton)**<a name="Swipe4UpButton"></a>
For four finger swiping. The button that is triggered by swiping up.
Integer value. A value of 0 disables swiping up. Defaults to 8.
**[Swipe4DownButton](#Swipe4DownButton)**<a name="Swipe4DownButton"></a>
For four finger swiping. The button that is triggered by swiping down.
Integer value. A value of 0 disables swiping down. Defaults to 9.
**[Swipe4LeftButton](#Swipe4LeftButton)**<a name="Swipe4LeftButton"></a>
For four finger swiping. The button that is triggered by swiping left.
Integer value. A value of 0 disables swiping left. Defaults to 10.
**[Swipe4RightButton](#Swipe4RightButton)**<a name="Swipe4RightButton"></a>
For four finger swiping. The button that is triggered by swiping right.
Integer value. A value of 0 disables swiping right. Defaults to 11.
---
##### Edge Scrolling - One finger
Should be used in conjuction with the [`Edge disabling`](#EdgeDisabling) options.
**[EdgeScrollDist](#EdgeScrollDist)**<a name="EdgeScrollDist"></a>
For one finger edge scrolling. How far you must move your finger on edge before
a button click is triggered.
Integer value. Defaults to 105.
**[EdgeScrollClickTime](#EdgeScrollClickTime)**<a name="EdgeScrollClickTime"></a>
For one finger edge scrolling. How long button triggered by edge scrolling
will be hold down. A value of 0 will hold button down till end of gesture.
0 - emit button click only once pre "instance" of gesture.
Integer value representing milliseconds. Defaults to 20.
**[EdgeScrollSensitivity](#EdgeScrollSensitivity)**<a name="EdgeScrollSensitivity"></a>
For one finger edge scrolling. Sensitivity (movement speed) of pointer during one
finger scrolling. A value of 0 disables pointer movement during gesture.
Integer value expressed as parts per thousand of normal sensivity.
A value of 1000 results with normal movement speed. Defaults to 0.
**[EdgeScrollUpButton](#EdgeScrollUpButton)**<a name="EdgeScrollUpButton"></a>
For one finger edge scrolling. The button that is triggered by edge scrolling up.
Integer value. A value of 0 disables scrolling up. Defaults to 4.
**[EdgeScrollDownButton](#EdgeScrollDownButton)**<a name="EdgeScrollDownButton"></a>
For one finger edge scrolling. The button that is triggered by edge scrolling down.
Integer value. A value of 0 disables scrolling down. Defaults to 5.
**[EdgeScrollLeftButton](#EdgeScrollLeftButton)**<a name="EdgeScrollLeftButton"></a>
For one finger edge scrolling. The button that is triggered by edge scrolling left.
Integer value. A value of 0 disables scrolling left. Defaults to 6.
**[EdgeScrollRightButton](#EdgeScrollRightButton)**<a name="EdgeScrollRightButton"></a>
For one finger edge scrolling. The button that is triggered by edge scrolling right.
Integer value. A value of 0 disables scrolling right. Defaults to 7.
---
##### Pinch scaling - Two fingers
**[ScaleDistance](#ScaleDistance)**<a name="ScaleDistance"></a>
For pinch scaling. How far you must move your fingers before a button click is
triggered.
Integer value. Defaults to 150.
**[ScaleUpButton](#ScaleUpButton)**<a name="ScaleUpButton"></a>
For pinch scaling. The button that is triggered by scaling up.
Integer value. A value of 0 disables scaling up. Defaults to 12.
**[ScaleDownButton](#ScaleDownButton)**<a name="ScaleDownButton"></a>
For pinch scaling. The button that is triggered by scaling down.
Integer value. A value of 0 disables scaling down. Defaults to 13.
---
##### Rotation - Two fingers
**[RotateDistance](#RotateDistance)**<a name="RotateDistance"></a>
For two finger rotation. How far you must move your fingers before a button
click is triggered.
Integer value. Defaults to 150.
**[RotateLeftButton](#RotateLeftButton)**<a name="RotateLeftButton"></a>
For two finger rotation. The button that is triggered by rotating left.
Integer value. A value of 0 disables rotation left. Defaults to 14.
**[RotateRightButton](#RotateRightButton)**<a name="RotateRightButton"></a>
For two finger rotation. The button that is triggered by rotating right.
Integer value. A value of 0 disables rotation right. Defaults to 15.
---
#### Edge disabling<a name="EdgeDisabling"></a>
~~[EdgeSize](#EdgeSize)~~<a name="EdgeSize"></a>
DEPRECATED.
The size of an area around the trackpad where new touches are ignored (fingers
traveling into this area from above will still be tracked).
This is represented as a percentage of the total trackpad height.
Integer value. Defaults to 0.
Value set here is overwriten by EdgeLeftSize, EdgeRightSize, EdgeTopSize and
EdgeBottomSize
**[EdgeTopSize](#EdgeTopSize)**<a name="EdgeTopSize"></a>
The size of an area at the top of the trackpad where new touches are ignored
(fingers travelling into this area from the bottom will still be tracked).
Integer value representing a percentage of the total trackpad height. Defaults to 0.
**[EdgeBottomSize](#EdgeBottomSize)**<a name="EdgeBottomSize"></a>
The size of an area at the bottom of the trackpad where new touches are ignored
(fingers travelling into this area from the top will still be tracked).
Integer value representing a percentage of the total trackpad height. Defaults to 10.
**[EdgeLeftSize](#EdgeLeftSize)**<a name="EdgeLeftSize"></a>
The size of an area at the left of the trackpad where new touches are ignored
(fingers travelling into this area from the right will still be tracked).
Integer value representing a percentage of the total trackpad width. Defaults to 0.
**[EdgeRightSize](#EdgeRightSize)**<a name="EdgeRightSize"></a>
The size of an area at the right of the trackpad where new touches are ignored
(fingers travelling into this area from the left will still be tracked).
Integer value representing a percentage of the total trackpad width. Defaults to 0.
---
#### Special features
**[Hold1Move1StationaryButton](#Hold1Move1StationaryButton)**<a name="Hold1Move1StationaryButton"></a>
For two finger hold-and-move functionality. The button that is triggered by
holding one finger and moving another one.
Integer value. A value of 0 disables hold-and-move.
Value of 0 disables this functionality.
Defaults to 1.
**[Hold1Move1StationaryMaxMove](#Hold1Move1StationaryMaxMove)**<a name="Hold1Move1StationaryMaxMove"></a>
For two finger hold-and-move functionality. Fow far stationary finger can be
moved berfore gesture invalidation.
Integer value. Default to 20.
**[TapDragEnable](#TapDragEnable)**<a name="TapDragEnable"></a>
Whether or not to enable tap-to-drag functionality.
Boolean value. Defaults to true.
**[TapDragTime](#TapDragTime)**<a name="TapDragTime"></a>
The tap-to-drag timeout. This is how long the driver will wait after a single
tap for a movement event before sending the click.
Integer value representing milliseconds. Defaults to 350.
**[TapDragWait](#TapDragWait)**<a name="TapDragWait"></a>
How long after detecting movement to trigger a button down event. During this
time pointer movement will be disabled. Increase this value if you find you're
draggin when you don't wish it.
Integer value representing milliseconds. Defaults to 40.
**[TapDragDist](#TapDragDist)**<a name="TapDragDist"></a>
How far the finger is allowed to move during drag wait time. If the finger
moves farther than this distance during the wait time then dragging will be
canceled and pointer movement will resume.
Integer value. Defaults to 200.
**[TapDragLockTimeout](#TapDragLockTimeout)**<a name="TapDragLockTimeout"></a>
This is how long the driver will wait after initial drag in 'drag ready' state
in which it will be able to resume previous drag without additional `up`, `down`
sequence.
Value of 0 disables this functionality.
Values of less than zero will make mtrack require additional tap to finish drag
by sending `button up`.
Integer value representing milliseconds. Defaults to 500.
**[AxisXInvert](#AxisXInvert)**<a name="AxisXInvert"></a>
Whether or not to invert the X axis.
Boolean value. Defaults to false.
**[AxisYInvert](#AxisYInvert)**<a name="AxisYInvert"></a>
Whether or not to invert the Y axis.
Boolean value. Defaults to false.
Tips
-------------
#### Swipe to drag
To setup swipe to drag functionality you have to choose which swipe gesture ([Scroll](two-finger-scrolling), [Swipe](#three-finger-swipe), [Swipe4](#four-finger-swipe))
will be used for dragging.
Example configuration for three finger drag:
```
Option "SwipeDistance" "1"
Option "SwipeLeftButton" "1"
Option "SwipeRightButton" "1"
Option "SwipeUpButton" "1"
Option "SwipeDownButton" "1"
Option "SwipeClickTime" "0"
Option "SwipeSensitivity" "1000"
```
This will enable dragging with three fingers. Change [sensitivity](#SwipeSensitivity) for faster/slower movements.
Scroll, and Swipe4 are also supported.
#### Hold and move
Hold down one finger in place to initiate hold-and-move gesture.
Then move another finger to drag configured button.
Gesture will last as long as fist finger (a.k.a. stationary finger) will
be held down in place.
Increase [TapDragDist](#TapDragDist) to give stationary finger more freedom.
Set [Hold1Move1StationaryButton](#Hold1Move1StationaryButton) to 0 to disable, set to other value to send button other
than "1".
#### Persistent dragging
If you're using lot of tools that require dragging you can make it a little bit
easier by enabling [persistent tap-to-drag](#TapDragLockTimeout):
```
Option "TapDragLockTimeout" "-1"
```
With that change you will have to perform additional tap when dragging with
tap-to-drag. Other positive values will let you continue yor drag within
specified time.
#### Enabling soft button
##### Basic
If you like to keep a finger on the bottom of the pad to click and use another one to move the cursor, you should enable edge restriction and [ClickFinger0](#ClickFinger0) parameters.
```
Option "EdgeBottomSize" "20" # Disable tap and movement detection in the bottom 20% of the pad
Option "ClickFinger0" "1" # Enable clicking action "1" when no finger is detected
```
You could also use [ClickFinger0](#ClickFinger0) with [EdgeTop/Right/LeftSize](#EdgeDisabling).
##### Advanced
If you want more than one button in the bottom edge, you need to use a more
advanced configuration. It will enable you use up to [3 buttons](#Zones) inside that [edge](#EdgeBottomSize).
```
Option "ButtonZonesEnable" "true" # Enable "Zones"
Option "LimitButtonZonesToBottomEdge" "true" # Limit the zones to the bottom edge
Option "EdgeBottomSize" "20" # Disable tap and movement detection in the bottom 20% of the pad
# Zones stack from left to right inside the 20% height defined above
Option "FirstZoneButton" "1" # Left part fire click 1
Option "SecondZoneButton" "3" # Middle part fire click 3
Option "ThirdZoneButton" "2" # Right part fire click 2
```
[1]: http://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt "Kernel Multitouch Protocol"
[2]: http://www.gnu.org/licenses/gpl-2.0.html "GNU General Public License, version 2"
[3]: http://bitmath.org/code/multitouch/ "xf86-input-multitouch website"
[4]: http://bitmath.org/code/mtdev/ "mtdev library website"
================================================
FILE: RELEASE.md
================================================
## v0.5.1
* Add button emulation when no finger placement is valid
* Add dedicated zone button
* Enable the restriction of the zone inside the bottom edge
* Readme configuration options are grouped according to their relationship
* Readme anchor has been moved to the options themselves
## v0.5.0
* Add tap-to-drag lock timeout
* Make edge size configurable for each edge individually
* Add edge scrolling
* Fix movement truncation
* Fix crash during suspend/wake up
* Make movement speed resolution independent
* Lock smooth scroll to one axis at time
* Post button events before move events
* New emulated buttons implementation
* Reduce max recognized fingers/touch points from 32 to 16
* New fancy readme with anchors
* Fix warnings, improve logging
* New examples
* Helper script to parse output of xinput --list-props
## v0.4.1
* Smooth scroll: detect and handle flipped up&down, left&right buttons
* Add examples with my current configuration as first example.
* Proper initialization of scroll axes(2 and 3).
* Setup scroll valuators also during device initialization.
* Do not consider edge clicks when calculating emulated buttons
* Change type of variables holding movement delta to double for better precision.
* Rewrite tap implementation from scratch. Remove 'status' field from Touch structure.
* Clear the MT_BUTTON bit of touches when an integrated button is released.
* Scale gesture reimplementation.
## v0.4.0
* Add smooth scroll
* Add scroll/swipe/swipe4 to drag functionality
* Add scroll coasting
* Add Hold And Move gesture
* Replace EdgeSize with BottomEdge property
* Replace busy waiting with timers
* Fix button down -> up delays
* Initial support for absolute mode devices
* Improve support for pressure based devices
* Many minor improvements/bugfixes
## v0.3.1
* Include a configure script.
* Update the README.
* Add the RELEASE file.
================================================
FILE: configure.ac
================================================
# Initialize Autoconf
AC_PREREQ([2.60])
AC_INIT([xf86-input-mtrack],
[0.2.0],
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
[xf86-input-mtrack])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_AUX_DIR(.)
# Initialize Automake
AM_INIT_AUTOMAKE([foreign subdir-objects])
AM_MAINTAINER_MODE
# Initialize libtool
AC_DISABLE_STATIC
AC_PROG_LIBTOOL
# Initialize X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS
m4_ifndef([XORG_MACROS_VERSION],
[m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])])
XORG_MACROS_VERSION(1.8)
XORG_DEFAULT_OPTIONS
# Checks for libraries.
AC_CHECK_LIB([mtdev], [mtdev_open])
AC_CHECK_LIB([m], [atan2])
# Obtain compiler/linker options for the mtrack driver dependencies
PKG_CHECK_MODULES(XORG, [xorg-server >= 1.7] xproto inputproto $REQUIRED_MODULES)
# Set driver name
DRIVER_NAME=mtrack
AC_SUBST([DRIVER_NAME])
# configure option for module install directory
AC_ARG_WITH(xorg-module-dir, AC_HELP_STRING([--with-xorg-module-dir=DIR],
[Default xorg module directory [[default=$libdir/xorg/modules]]]),
[moduledir="$withval"],
[moduledir="$libdir/xorg/modules"])
inputdir=${moduledir}/input
AC_SUBST(inputdir)
# configure option to build extra tools
AC_ARG_ENABLE(tools, AC_HELP_STRING([--enable-tools],
[Build extra tools (default: disabled)]),
[ENABLE_TOOLS=yes],
[ENABLE_TOOLS=no])
AM_CONDITIONAL([BUILD_TOOLS], [test "x$ENABLE_TOOLS" = xyes])
# configure option to enable gesture ate debugging
AC_ARG_ENABLE(debug-gestures, AS_HELP_STRING([--enable-debug-gestures],
[Enable gesture debugging (default: disabled)]),
[DEBUG_GESTURES=yes],
[DEBUG_GESTURES=no])
if test "x$DEBUG_GESTURES" = xyes; then
AC_DEFINE(DEBUG_GESTURES, 1, [Enable gesture debugging.])
fi
# configure option to enable multitouch state debugging
AC_ARG_ENABLE(debug-mtstate, AS_HELP_STRING([--enable-debug-mtstate],
[Enable multitouch state debugging (default: disabled)]),
[DEBUG_MTSTATE=yes],
[DEBUG_MTSTATE=no])
if test "x$DEBUG_MTSTATE" = xyes; then
AC_DEFINE(DEBUG_MTSTATE, 1, [Enable multitouch state debugging.])
fi
# configure option to enable property debugging
AC_ARG_ENABLE(debug-props, AS_HELP_STRING([--enable-debug-props],
[Enable property debugging (default: disabled)]),
[DEBUG_PROPS=yes],
[DEBUG_PROPS=no])
if test "x$DEBUG_PROPS" = xyes; then
AC_DEFINE(DEBUG_PROPS, 1, [Enable property debugging.])
fi
# configure option to enable driver debugging
AC_ARG_ENABLE(debug-driver, AS_HELP_STRING([--enable-debug-driver],
[Enable property debugging (default: disabled)]),
[DEBUG_DRIVER=yes],
[DEBUG_DRIVER=no])
if test "x$DEBUG_DRIVER" = xyes; then
AC_DEFINE(DEBUG_DRIVER, 1, [Enable property debugging.])
fi
# configure option to enable all debugging
AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],
[Enable all debugging (default: disabled)]),
[DEBUG_ALL=$enableval],
[DEBUG_ALL=no])
if test "x$DEBUG_ALL" = xyes; then
AC_DEFINE(DEBUG_GESTURES, 1, [Enable gesture debugging.])
AC_DEFINE(DEBUG_MTSTATE, 1, [Enable multitouch state debugging.])
AC_DEFINE(DEBUG_PROPS, 1, [Enable property debugging.])
AC_DEFINE(DEBUG_DRIVER, 1, [Enable driver debugging.])
fi
# Everything else
AC_PROG_CC
AC_PROG_INSTALL
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
================================================
FILE: debian/README.Debian
================================================
Xorg Multitouch Trackpad Driver
* Install the Debian package
* Configure xorg.conf
* Restart X
================================================
FILE: debian/changelog
================================================
xserver-xorg-input-mtrack (0.5.0) unstable; urgency=medium
* Add tap-to-drag lock timeout
* Make edge size configurable for each edge individually
* Add edge scrolling
* Fix movement truncation
* Fix crash during suspend/wake up
* Make movement speed resolution independent
* Lock smooth scroll to one axis at time
* Post button events before move events
* New emulated buttons implementation
* Reduce max recognized fingers/touch points from 32 to 16
* New fancy readme with anchors
* Fix warnings, improve logging
* New examples
* Helper script to parse output of xinput --list-props
-- Paweł Turkowski <p2rkw0@gmail.com> Sun, 28 Jan 2018 20:02:28 +0100
xserver-xorg-input-mtrack (0.4.1) unstable; urgency=low
* Smooth scroll: detect and handle flipped up&down, left&right buttons
* Add examples with my current configuration as first example.
* Proper initialization of scroll axes(2 and 3).
* Setup scroll valuators also during device initialization.
* Do not consider edge clicks when calculating emulated buttons
* Change type of variables holding movement delta to double for better precision.
* Rewrite tap implementation from scratch. Remove 'status' field from Touch structure.
* Clear the MT_BUTTON bit of touches when an integrated button is released.
* Scale gesture reimplementation.
-- Paweł Turkowski <p2rkw0@gmail.com> Wed, 02 Nov 2016 00:13:04 +0100
xserver-xorg-input-mtrack (0.4.0) unstable; urgency=low
* Add smooth scroll
* Add scroll/swipe/swipe4 to drag functionality
* Add scroll coasting
* Add scroll/swipe/swipe4 click time
* Add Hold And Move gesture
* Replace EdgeSize with BottomEdge property
* Replace busy waiting with timers
* Fix button down -> up delays
* Initial support for absolute mode devices
* Improve support for pressure based devices
* Many minor improvements/bugfixes
-- Paweł Turkowski <p2rkw0@gmail.com> Mon, 28 Sep 2015 01:20:38 +0200
xserver-xorg-input-mtrack (0.2.0) unstable; urgency=low
* Now built via autoconf/automake.
* Fully configurable via XInput.
* Sensitivify now configurable.
* Trackpad can now be disabled on keystroke via an external daemon.
* Four finger tapping/swiping added.
* Button zones added, a new button emulation method.
* Tap-to-drag fixed.
* Three finger tapping responsiveness fixed.
-- Ryan Bourgeois <bluedragonx@gmail.com> Thu, 26 May 2011 09:44:43 -0500
xserver-xorg-input-mtrack (0.1.1) unstable; urgency=low
* Bugfix release.
* Disabling tapping no longer (wrongly) disables pointer movement.
* Button emulation set to ignore "old" touches. What consitutes an old touch can be adjusted with the ButtonTouchExpire option.
-- Ryan Bourgeois <bluedragonx@gmail.com> Thu, 28 Apr 2011 01:14:58 -0500
xserver-xorg-input-mtrack (0.1.0) unstable; urgency=low
* Initial release.
-- Ryan Bourgeois <bluedragonx@gmail.com> Fri, 15 Apr 2011 14:46:10 -0500
================================================
FILE: debian/compat
================================================
5
================================================
FILE: debian/control
================================================
Source: xserver-xorg-input-mtrack
Section: misc
Priority: optional
Maintainer: Paweł Turkowski <p2rkw0@gmail.com>
Build-Depends:
debhelper (>= 5),
xserver-xorg-dev (>= 2:1.7.6),
libmtdev-dev (>= 1.0.10)
Standards-Version: 3.7.2
Homepage: https://github.com/p2rkw/xf86-input-mtrack
Package: xserver-xorg-input-mtrack
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, libmtdev1 (>= 1.0)
Description: Xorg Multitouch Trackpad Driver
This X input driver provides gestures support for multitouch touchpads,
with or without an integrated button.
================================================
FILE: debian/copyright
================================================
Source URL: https://github.com/p2rkw/xf86-input-mtrack
Upstream Authors: Ryan Bourgeois <bluedragonx@gmail.com>
Paweł Turkowski <p2rkw0@gmail.com>
Copyright:
Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se)
Copyright (C) 2011 Ryan Bourgeois (bluedragonx@gmail.com)
Copyright (C) 2018 Paweł Turkowski (p2rkw0@gmail.com)
License:
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Packaging:
Copyright (C) 2008 by Henrik Rydberg <rydberg@euromail.se>
Copyright (C) 2011 by Ryan Bourgeois <bluedragonx@gmail.com>
Copyright (C) 2018 by Paweł Turkowski <p2rkw0@gmail.com>
released under GPL 2
================================================
FILE: debian/dirs
================================================
================================================
FILE: debian/rules
================================================
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
build-arch:
dh_testdir
$(MAKE)
build-indep:
build: build-arch build-indep
install:
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
$(MAKE) DESTDIR=$(CURDIR)/debian/xserver-xorg-input-mtrack install
binary-arch: build-arch install
dh_testdir
dh_testroot
dh_link
dh_strip
dh_compress
dh_fixperms
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary-indep: build-indep
binary: binary-arch binary-indep
clean:
dh_testdir
dh_testroot
$(MAKE) clean
dh_clean
.PHONY: build-arch build-indep build install binary-arch binary-indep binary clean
================================================
FILE: driver/mprops.c
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#include "mprops.h"
#include "common.h"
#include "mtouch.h"
#ifdef DEBUG_PROPS
# define LOG_DEBUG_PROPS LOG_DEBUG
#else
# define LOG_DEBUG_PROPS LOG_DISABLED
#endif
#define MAX_INT_VALUES 7
#define MAX_FLOAT_VALUES 4
#define MAX_BUTTON_VALUES 6
#define VALID_BUTTON(x) (x >= 0 && x <= 32)
#define VALID_BOOL(x) (x == 0 || x == 1)
#define VALID_PCNT(x) (x >= 0 && x <= 100)
struct MProps mprops;
Atom atom_init_integer(DeviceIntPtr dev, char* name, int nvalues, int* values, int size) {
Atom atom;
int i;
uint8_t uvals8[MAX_INT_VALUES];
uint16_t uvals16[MAX_INT_VALUES];
uint32_t uvals32[MAX_INT_VALUES];
pointer uvals;
nvalues = MINVAL(MAX_INT_VALUES, nvalues);
switch(size) {
case 8:
for (i = 0; i < nvalues; i++) {
uvals8[i] = values[i];
}
uvals = uvals8;
break;
case 16:
for (i = 0; i < nvalues; i++) {
uvals16[i] = values[i];
}
uvals = uvals16;
break;
default:
for (i = 0; i < nvalues; i++) {
uvals32[i] = values[i];
}
uvals = uvals32;
break;
}
atom = MakeAtom(name, strlen(name), TRUE);
XIChangeDeviceProperty(dev, atom, XA_INTEGER, size, PropModeReplace, nvalues, uvals, FALSE);
XISetDevicePropertyDeletable(dev, atom, FALSE);
return atom;
}
static
Atom atom_init_integers32(DeviceIntPtr dev, char* name, int nvalues, int* values) {
int size = 32;
Atom atom;
atom = MakeAtom(name, strlen(name), TRUE);
XIChangeDeviceProperty(dev, atom, XA_INTEGER, size, PropModeReplace, nvalues, values, FALSE);
XISetDevicePropertyDeletable(dev, atom, FALSE);
return atom;
}
Atom atom_init_float(DeviceIntPtr dev, char* name, int nvalues, float* values, Atom float_type) {
Atom atom = MakeAtom(name, strlen(name), TRUE);
XIChangeDeviceProperty(dev, atom, float_type, 32, PropModeReplace, nvalues, values, FALSE);
XISetDevicePropertyDeletable(dev, atom, FALSE);
return atom;
}
static void init_swipe_props(DeviceIntPtr dev, struct MPropsSwipe* props_swipe,
struct MConfigSwipe* cfg_swipe, char const* settings_prop_name,
char const* buttons_prop_name){
int ivals[MAX_INT_VALUES];
ivals[0] = cfg_swipe->dist;
ivals[1] = cfg_swipe->hold;
ivals[2] = cfg_swipe->drag_sens;
props_swipe->settings = atom_init_integer(dev, (char*)settings_prop_name, 3, ivals, 32);
ivals[0] = cfg_swipe->up_btn;
ivals[1] = cfg_swipe->dn_btn;
ivals[2] = cfg_swipe->lt_btn;
ivals[3] = cfg_swipe->rt_btn;
props_swipe->buttons = atom_init_integer(dev, (char*)buttons_prop_name, 4, ivals, 8);
}
static void init_edge_props(DeviceIntPtr dev, Atom* props_edge,
struct MConfigSwipe* cfg_edge, char const* settings_prop_name){
static const int nvalues = 7;
int ivals[nvalues];
ivals[0] = cfg_edge->dist;
ivals[1] = cfg_edge->hold;
ivals[2] = cfg_edge->drag_sens;
ivals[3] = cfg_edge->up_btn;
ivals[4] = cfg_edge->dn_btn;
ivals[5] = cfg_edge->lt_btn;
ivals[6] = cfg_edge->rt_btn;
*props_edge = atom_init_integers32(dev, (char*)settings_prop_name, nvalues, ivals);
}
void mprops_init(struct MConfig* cfg, InputInfoPtr local) {
int ivals[MAX_INT_VALUES];
float fvals[MAX_FLOAT_VALUES];
mprops.float_type = XIGetKnownProperty(XATOM_FLOAT);
if (!mprops.float_type) {
mprops.float_type = MakeAtom(XATOM_FLOAT, strlen(XATOM_FLOAT), TRUE);
if (!mprops.float_type) {
LOG_ERROR("%s: Failed to init float atom. Property support is disabled.\n", local->name);
return;
}
}
ivals[0] = cfg->trackpad_disable;
mprops.trackpad_disable = atom_init_integer(local->dev, MTRACK_PROP_TRACKPAD_DISABLE, 1, ivals, 8);
fvals[0] = (float)cfg->sensitivity;
mprops.sensitivity = atom_init_float(local->dev, MTRACK_PROP_SENSITIVITY, 1, fvals, mprops.float_type);
ivals[0] = cfg->touch_down;
ivals[1] = cfg->touch_up;
mprops.pressure = atom_init_integer(local->dev, MTRACK_PROP_PRESSURE, 2, ivals, 8);
ivals[0] = cfg->button_enable;
ivals[1] = cfg->button_integrated;
mprops.button_settings = atom_init_integer(local->dev, MTRACK_PROP_BUTTON_SETTINGS, 2, ivals, 8);
ivals[0] = cfg->button_zones;
ivals[1] = cfg->button_move;
ivals[2] = cfg->button_expire;
ivals[3] = cfg->is_button_zones_height_limited;
mprops.button_emulate_settings = atom_init_integer(local->dev, MTRACK_PROP_BUTTON_EMULATE_SETTINGS, 4, ivals, 16);
ivals[0] = cfg->button_0touch;
ivals[1] = cfg->button_1touch;
ivals[2] = cfg->button_2touch;
ivals[3] = cfg->button_3touch;
ivals[4] = cfg->button_first_zone;
ivals[5] = cfg->button_second_zone;
ivals[6] = cfg->button_third_zone;
mprops.button_emulate_values = atom_init_integer(local->dev, MTRACK_PROP_BUTTON_EMULATE_VALUES, 7, ivals, 8);
ivals[0] = cfg->tap_hold;
ivals[1] = cfg->tap_timeout;
ivals[2] = cfg->tap_dist;
mprops.tap_settings = atom_init_integer(local->dev, MTRACK_PROP_TAP_SETTINGS, 3, ivals, 32);
ivals[0] = cfg->tap_1touch;
ivals[1] = cfg->tap_2touch;
ivals[2] = cfg->tap_3touch;
ivals[3] = cfg->tap_4touch;
mprops.tap_emulate = atom_init_integer(local->dev, MTRACK_PROP_TAP_EMULATE, 4, ivals, 8);
ivals[0] = cfg->ignore_thumb;
ivals[1] = cfg->disable_on_thumb;
mprops.thumb_detect = atom_init_integer(local->dev, MTRACK_PROP_THUMB_DETECT, 2, ivals, 8);
ivals[0] = cfg->thumb_size;
ivals[1] = cfg->thumb_ratio;
mprops.thumb_size = atom_init_integer(local->dev, MTRACK_PROP_THUMB_SIZE, 2, ivals, 32);
ivals[0] = cfg->ignore_palm;
ivals[1] = cfg->disable_on_palm;
mprops.palm_detect = atom_init_integer(local->dev, MTRACK_PROP_PALM_DETECT, 2, ivals, 8);
ivals[0] = cfg->palm_size;
mprops.palm_size = atom_init_integer(local->dev, MTRACK_PROP_PALM_SIZE, 1, ivals, 32);
ivals[0] = cfg->gesture_hold;
ivals[1] = cfg->gesture_wait;
mprops.gesture_settings = atom_init_integer(local->dev, MTRACK_PROP_GESTURE_SETTINGS, 2, ivals, 16);
ivals[0] = cfg->scroll_smooth;
mprops.scroll_smooth = atom_init_integer(local->dev, MTRACK_PROP_SMOOTH_SCROLL, 1, ivals, 8);
init_swipe_props(local->dev, &mprops.scroll, &cfg->scroll, MTRACK_PROP_SCROLL_SETTINGS, MTRACK_PROP_SCROLL_BUTTONS);
init_swipe_props(local->dev, &mprops.swipe3, &cfg->swipe3, MTRACK_PROP_SWIPE_SETTINGS, MTRACK_PROP_SWIPE_BUTTONS);
init_swipe_props(local->dev, &mprops.swipe4, &cfg->swipe4, MTRACK_PROP_SWIPE4_SETTINGS, MTRACK_PROP_SWIPE4_BUTTONS);
fvals[0] = cfg->scroll_coast.min_speed;
fvals[1] = cfg->scroll_coast.duration; /* = duration in miliseconds */
mprops.scroll_coast = atom_init_float(local->dev, MTRACK_PROP_SCROLL_COAST, 2, fvals, mprops.float_type);
init_edge_props(local->dev, &mprops.edge_scroll, &cfg->edge_scroll, MTRACK_PROP_EDGE_SCROLL_SETTINGS);
ivals[0] = cfg->edge_top_size;
ivals[1] = cfg->edge_bottom_size;
ivals[2] = cfg->edge_left_size;
ivals[3] = cfg->edge_right_size;
mprops.edge_sizes = atom_init_integer(local->dev, MTRACK_PROP_EDGE_SIZES, 4, ivals, 8);
ivals[0] = cfg->scale_dist;
mprops.scale_dist = atom_init_integer(local->dev, MTRACK_PROP_SCALE_DIST, 1, ivals, 32);
ivals[0] = cfg->scale_up_btn;
ivals[1] = cfg->scale_dn_btn;
mprops.scale_buttons = atom_init_integer(local->dev, MTRACK_PROP_SCALE_BUTTONS, 2, ivals, 8);
ivals[0] = cfg->rotate_dist;
mprops.rotate_dist = atom_init_integer(local->dev, MTRACK_PROP_ROTATE_DIST, 1, ivals, 32);
ivals[0] = cfg->rotate_lt_btn;
ivals[1] = cfg->rotate_rt_btn;
mprops.rotate_buttons = atom_init_integer(local->dev, MTRACK_PROP_ROTATE_BUTTONS, 2, ivals, 8);
ivals[0] = cfg->hold1_move1_stationary.max_move;
ivals[1] = cfg->hold1_move1_stationary.button;
mprops.hold1_move1_stationary = atom_init_integer(local->dev, MTRACK_PROP_HOLD1_MOVE1_STATIONARY_SETTINGS, 2, ivals, 32);
init_swipe_props(local->dev, &mprops.hold1_move1, &cfg->hold1_move1, MTRACK_PROP_HOLD1_MOVE1_SETTINGS, MTRACK_PROP_HOLD1_MOVE1_BUTTONS);
#if 0
ivals[0] = cfg->hold1_move2_stationary.max_move;
ivals[1] = cfg->hold1_move2_stationary.button;
mprops.hold1_move2_stationary = atom_init_integer(local->dev, MTRACK_PROP_HOLD1_MOVE2_STATIONARY_SETTINGS, 2, ivals, 32);
init_swipe_props(local->dev, &mprops.hold1_move2, &cfg->hold1_move2, MTRACK_PROP_HOLD1_MOVE2_SETTINGS, MTRACK_PROP_HOLD1_MOVE2_BUTTONS);
ivals[0] = cfg->hold1_move3_stationary.max_move;
ivals[1] = cfg->hold1_move3_stationary.button;
mprops.hold1_move3_stationary = atom_init_integer(local->dev, MTRACK_PROP_HOLD1_MOVE3_STATIONARY_SETTINGS, 2, ivals, 32);
init_swipe_props(local->dev, &mprops.hold1_move3, &cfg->hold1_move3, MTRACK_PROP_HOLD1_MOVE3_SETTINGS, MTRACK_PROP_HOLD1_MOVE3_BUTTONS);
#endif
ivals[0] = cfg->drag_enable;
ivals[1] = cfg->drag_timeout;
ivals[2] = cfg->drag_wait;
ivals[3] = cfg->drag_dist;
ivals[4] = cfg->drag_lock_timeout;
mprops.drag_settings = atom_init_integer(local->dev, MTRACK_PROP_DRAG_SETTINGS, 5, ivals, 32);
ivals[0] = cfg->axis_x_invert;
ivals[1] = cfg->axis_y_invert;
mprops.axis_invert = atom_init_integer(local->dev, MTRACK_PROP_AXIS_INVERT, 2, ivals, 8);
}
int check_buttons_property(XIPropertyValuePtr prop, uint8_t** buttons_ret_arr, int buttons_count)
{
uint8_t* ivals8;
int i;
if (prop->size != buttons_count || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
for (i = 0; i < buttons_count; ++i) {
if (!VALID_BUTTON(ivals8[i]))
return BadMatch;
}
*buttons_ret_arr = ivals8;
return Success;
}
/* Return:
* 1 - property was recognized and handled with or without error, check error code for details
* 0 - property not recognized, don't trust returned error code - it's invalid
*/
static int set_swipe_properties(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
BOOL checkonly,
struct MPropsSwipe* props_swipe,
struct MConfigSwipe* cfg_swipe, int* error_code){
uint8_t* ivals8;
uint32_t* ivals32;
*error_code = Success;
if (property == props_swipe->settings) {
if (prop->size != 3 || prop->format != 32 || prop->type != XA_INTEGER)
return *error_code = BadMatch, 1;
ivals32 = (uint32_t*)prop->data;
if (ivals32[0] < 1 || (int)(ivals32[1]) < 0)
return *error_code = BadMatch, 1;
if (!checkonly) {
cfg_swipe->dist = ivals32[0];
cfg_swipe->hold = ivals32[1];
cfg_swipe->drag_sens = ivals32[2];
LOG_DEBUG_PROPS("set swipe settings: dist: %d hold: %d\n",
cfg_swipe->dist, cfg_swipe->hold);
}
}
else if (property == props_swipe->buttons) {
if (check_buttons_property(prop, &ivals8, 4) == Success){
if (!checkonly) {
cfg_swipe->up_btn = ivals8[0];
cfg_swipe->dn_btn = ivals8[1];
cfg_swipe->lt_btn = ivals8[2];
cfg_swipe->rt_btn = ivals8[3];
}
}
else
return *error_code = BadMatch, 1;
}
else{
return 0;
}
return 1;
}
int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, BOOL checkonly) {
InputInfoPtr local = dev->public.devicePrivate;
struct MConfig* cfg = &((struct MTouch*)local->private)->cfg;
uint8_t* ivals8;
uint16_t* ivals16;
uint32_t* ivals32;
float* fvals;
int error_code;
if (property == mprops.trackpad_disable) {
if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (ivals8[0] < 0 || ivals8[0] > 3)
return BadMatch;
if (!checkonly) {
cfg->trackpad_disable = ivals8[0];
if (cfg->trackpad_disable)
LOG_DEBUG_PROPS("trackpad input disabled\n");
else
LOG_DEBUG_PROPS("trackpad input enabled\n");
}
}
else if (property == mprops.sensitivity) {
if (prop->size != 1 || prop->format != 32 || prop->type != mprops.float_type)
return BadMatch;
fvals = (float*)prop->data;
if (fvals[0] < 0)
return BadMatch;
if (!checkonly) {
cfg->sensitivity = fvals[0];
LOG_DEBUG_PROPS("set sensitivity to %f\n", cfg->sensitivity);
}
}
else if (property == mprops.pressure) {
if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_PCNT(ivals8[0]) || !VALID_PCNT(ivals8[1]))
return BadMatch;
if (!checkonly) {
cfg->touch_down = ivals8[0];
cfg->touch_up = ivals8[1];
LOG_DEBUG_PROPS("set touch pressure to %d %d\n",
cfg->touch_down, cfg->touch_up);
}
}
else if (property == mprops.button_settings) {
if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
return BadMatch;
if (!checkonly) {
cfg->button_enable = ivals8[0];
cfg->button_integrated = ivals8[1];
LOG_DEBUG_PROPS("set button settings to %d %d\n",
cfg->button_enable, cfg->button_integrated);
}
}
else if (property == mprops.button_emulate_settings) {
if (prop->size != 3 || prop->format != 16 || prop->type != XA_INTEGER)
return BadMatch;
ivals16 = (uint16_t*)prop->data;
if (!VALID_BOOL(ivals16[0]) || !VALID_BOOL(ivals16[1]) || ivals16[2] < 0)
return BadMatch;
if (!checkonly) {
cfg->button_zones = ivals16[0];
cfg->button_move = ivals16[1];
cfg->button_expire = ivals16[2];
LOG_DEBUG_PROPS("set button emulate settings to %d %d %d\n",
cfg->button_zones, cfg->button_move, cfg->button_expire);
}
}
else if (property == mprops.button_emulate_values) {
if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
return BadMatch;
if (!checkonly) {
cfg->button_0touch = ivals8[0];
cfg->button_1touch = ivals8[1];
cfg->button_2touch = ivals8[2];
cfg->button_3touch = ivals8[3];
LOG_DEBUG_PROPS("set button emulation to %d %d %d %d\n",
cfg->button_0touch, cfg->button_1touch, cfg->button_2touch, cfg->button_3touch);
}
}
else if (property == mprops.tap_settings) {
if (prop->size != 3 || prop->format != 32 || prop->type != XA_INTEGER)
return BadMatch;
ivals32 = (uint32_t*)prop->data;
if (ivals32[0] < 1 || ivals32[1] < 1 || ivals32[2] < 1)
return BadMatch;
if (!checkonly) {
cfg->tap_hold = ivals32[0];
cfg->tap_timeout = ivals32[1];
cfg->tap_dist = ivals32[2];
LOG_DEBUG_PROPS("set tap settings to %d %d %d\n",
cfg->tap_hold, cfg->tap_timeout, cfg->tap_dist);
}
}
else if (property == mprops.tap_emulate) {
if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
return BadMatch;
if (!checkonly) {
cfg->tap_1touch = ivals8[0];
cfg->tap_2touch = ivals8[1];
cfg->tap_3touch = ivals8[2];
cfg->tap_4touch = ivals8[3];
LOG_DEBUG_PROPS("set tap emulation to %d %d %d %d\n",
cfg->tap_1touch, cfg->tap_2touch, cfg->tap_3touch, cfg->tap_4touch);
}
}
else if (property == mprops.thumb_detect) {
if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
return BadMatch;
if (!checkonly) {
cfg->ignore_thumb = ivals8[0];
cfg->disable_on_thumb = ivals8[1];
LOG_DEBUG_PROPS("set thumb detect to %d %d\n",
cfg->ignore_thumb, cfg->disable_on_thumb);
}
}
else if (property == mprops.thumb_size) {
if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
return BadMatch;
ivals32 = (uint32_t*)prop->data;
if (ivals32[0] < 0 || !VALID_PCNT(ivals32[1]))
return BadMatch;
if (!checkonly) {
cfg->thumb_size = ivals32[0];
cfg->thumb_ratio = ivals32[0];
LOG_DEBUG_PROPS("set thumb size to %d %d\n",
cfg->thumb_size, cfg->thumb_ratio);
}
}
else if (property == mprops.palm_detect) {
if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
return BadMatch;
if (!checkonly) {
cfg->ignore_palm = ivals8[0];
cfg->disable_on_palm = ivals8[1];
LOG_DEBUG_PROPS("set palm detect to %d %d\n",
cfg->ignore_palm, cfg->disable_on_palm);
}
}
else if (property == mprops.palm_size) {
if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
return BadMatch;
ivals32 = (uint32_t*)prop->data;
if (ivals32[0] < 0)
return BadMatch;
if (!checkonly) {
cfg->palm_size = ivals32[0];
LOG_DEBUG_PROPS("set palm size to %d\n",
cfg->palm_size);
}
}
else if (property == mprops.gesture_settings) {
if (prop->size != 2 || prop->format != 16 || prop->type != XA_INTEGER)
return BadMatch;
ivals16 = (uint16_t*)prop->data;
if (ivals16[0] < 1 || ivals16[1] < 0)
return BadMatch;
if (!checkonly) {
cfg->gesture_hold = ivals16[0];
cfg->gesture_wait = ivals16[1];
LOG_DEBUG_PROPS("set gesture settings to %d %d\n",
cfg->gesture_hold, cfg->gesture_wait);
}
}
else if (property == mprops.scroll_smooth) {
if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_BOOL(ivals8[0]))
return BadMatch;
if (!checkonly) {
cfg->scroll_smooth = ivals8[0];
LOG_DEBUG_PROPS("set high precision scrolling to %d\n",
cfg->scroll_smooth);
}
}
else if (set_swipe_properties(dev, property, prop, checkonly, &mprops.scroll, &cfg->scroll, &error_code)) {
return error_code;
}
else if (property == mprops.scroll_coast) {
if (prop->size != 2 || prop->type != mprops.float_type)
return BadMatch;
fvals = (float*)prop->data;
if (fvals[0] < 0.0f || fvals[1] < 0.0f)
return BadMatch;
if (!checkonly) {
cfg->scroll_coast.min_speed = fvals[0];
cfg->scroll_coast.duration = fvals[1];
LOG_DEBUG_PROPS("set scroll coasting to %f %f\n",
cfg->scroll_coast.min_speed, cfg->scroll_coast.duration);
}
}
else if (property == mprops.edge_scroll) {
if (prop->size != 7 || prop->format != 32 || prop->type != XA_INTEGER)
return BadMatch;
ivals32 = (uint32_t*)prop->data;
if (!checkonly) {
cfg->edge_scroll.dist = ivals32[0];
cfg->edge_scroll.hold = ivals32[1];
cfg->edge_scroll.drag_sens = ivals32[2];
cfg->edge_scroll.up_btn = ivals32[3];
cfg->edge_scroll.dn_btn = ivals32[4];
cfg->edge_scroll.lt_btn = ivals32[5];
cfg->edge_scroll.rt_btn = ivals32[6];
}
}
else if (property == mprops.scale_dist) {
if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
return BadMatch;
ivals32 = (uint32_t*)prop->data;
if (ivals32[0] < 1)
return BadMatch;
if (!checkonly) {
cfg->scale_dist = ivals32[0];
LOG_DEBUG_PROPS("set scale distance to %d\n",
cfg->scale_dist);
}
}
else if (set_swipe_properties(dev, property, prop, checkonly, &mprops.swipe3, &cfg->swipe3, &error_code)) {
return error_code;
}
else if (set_swipe_properties(dev, property, prop, checkonly, &mprops.swipe4, &cfg->swipe4, &error_code)) {
return error_code;
}
else if (property == mprops.scale_buttons) {
if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]))
return BadMatch;
if (!checkonly) {
cfg->scale_up_btn = ivals8[0];
cfg->scale_dn_btn = ivals8[1];
LOG_DEBUG_PROPS("set scale buttons to %d %d\n",
cfg->scale_up_btn, cfg->scale_dn_btn);
}
}
else if (property == mprops.rotate_dist) {
if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
return BadMatch;
ivals32 = (uint32_t*)prop->data;
if (ivals32[0] < 1)
return BadMatch;
if (!checkonly) {
cfg->rotate_dist = ivals32[0];
LOG_DEBUG_PROPS("set rotate distance to %d\n",
cfg->rotate_dist);
}
}
else if (property == mprops.rotate_buttons) {
if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]))
return BadMatch;
if (!checkonly) {
cfg->rotate_lt_btn = ivals8[0];
cfg->rotate_rt_btn = ivals8[1];
LOG_DEBUG_PROPS("set rotate buttons to %d %d\n",
cfg->rotate_lt_btn, cfg->rotate_rt_btn);
}
}
else if (property == mprops.hold1_move1_stationary){
if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
return BadMatch;
ivals32 = (uint32_t*)prop->data;
if (ivals32[0] < 0|| !VALID_BUTTON(ivals32[1]))
return BadMatch;
if (!checkonly) {
cfg->hold1_move1_stationary.max_move = ivals32[0];
cfg->hold1_move1_stationary.button = ivals32[1];
LOG_DEBUG_PROPS("hold1_move1: max_move %d; button: %d\n",
cfg->hold1_move1_stationary.max_move, cfg->hold1_move1_stationary.button);
}
}
else if (set_swipe_properties(dev, property, prop, checkonly, &mprops.hold1_move1, &cfg->hold1_move1, &error_code)) {
return error_code;
}
#if 0
else if (property == mprops.hold1_move2_stationary){
if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
return BadMatch;
ivals32 = (uint32_t*)prop->data;
if (ivals32[0] < 0|| !VALID_BUTTON(ivals32[1]))
return BadMatch;
if (!checkonly) {
cfg->hold1_move2_stationary.max_move = ivals32[0];
cfg->hold1_move2_stationary.button = ivals32[1];
LOG_DEBUG_PROPS("hold1_move2: max_move %d; button: %d\n",
cfg->hold1_move2_stationary.max_move, cfg->hold1_move2_stationary.button);
}
}
else if (set_swipe_properties(dev, property, prop, checkonly, &mprops.hold1_move2, &cfg->hold1_move2, &error_code)) {
return error_code;
}
else if (property == mprops.hold1_move3_stationary){
if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
return BadMatch;
ivals32 = (uint32_t*)prop->data;
if (ivals32[0] < 0|| !VALID_BUTTON(ivals32[1]))
return BadMatch;
if (!checkonly) {
cfg->hold1_move3_stationary.max_move = ivals32[0];
cfg->hold1_move3_stationary.button = ivals32[1];
LOG_DEBUG_PROPS("hold1_move1: max_move %d; button: %d\n",
cfg->hold1_move3_stationary.max_move, cfg->hold1_move3_stationary.button);
}
}
else if (set_swipe_properties(dev, property, prop, checkonly, &mprops.hold1_move3, &cfg->hold1_move3, &error_code)) {
return error_code;
}
#endif
else if (property == mprops.drag_settings) {
if (prop->size != 5 || prop->format != 32 || prop->type != XA_INTEGER)
return BadMatch;
ivals32 = (uint32_t*)prop->data;
if (!VALID_BOOL(ivals32[0]) || ivals32[1] < 1 || (int)(ivals32[2]) < 0 || (int)(ivals32[3]) < 0)
return BadMatch;
if (!checkonly) {
cfg->drag_enable = ivals32[0];
cfg->drag_timeout = ivals32[1];
cfg->drag_wait = ivals32[2];
cfg->drag_dist = ivals32[3];
cfg->drag_lock_timeout = ivals32[4];
LOG_DEBUG_PROPS("set drag settings to %d %d %d %d %d\n",
cfg->drag_enable, cfg->drag_timeout, cfg->drag_wait, cfg->drag_dist, cfg->drag_lock_timeout);
}
}
else if (property == mprops.axis_invert) {
if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
return BadMatch;
if (!checkonly) {
cfg->axis_x_invert = ivals8[0];
cfg->axis_y_invert = ivals8[1];
LOG_DEBUG_PROPS("set axis inversion to %d %d\n",
cfg->axis_x_invert, cfg->axis_y_invert);
}
}
else if (property == mprops.edge_sizes) {
if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
return BadMatch;
ivals8 = (uint8_t*)prop->data;
if (!VALID_PCNT(ivals8[0]) || !VALID_PCNT(ivals8[1]) || !VALID_PCNT(ivals8[2]) || !VALID_PCNT(ivals8[3]))
return BadMatch;
if (!checkonly) {
cfg->edge_top_size = ivals8[0];
cfg->edge_bottom_size = ivals8[1];
cfg->edge_left_size = ivals8[2];
cfg->edge_right_size = ivals8[3];
LOG_DEBUG_PROPS("set edge sizes to %d %d %d %d\n",
cfg->edge_left_size, cfg->edge_right_size, cfg->edge_top_size, cfg->edge_bottom_size);
}
}
return Success;
}
================================================
FILE: driver/mtrack.c
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
* Copyright (C) 2015-2018 Paweł Turkowski <p2rkw0@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#include "mtouch.h"
#include "mprops.h"
#include "capabilities.h"
#include "os.h"
#include "trig.h" /* xorg/os.h for timers */
#include <xf86Module.h>
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
#include <X11/Xatom.h>
#include <xserver-properties.h>
#endif
#include <math.h> /* cos */
#define TAP_HOLD 100
#define TAP_TIMEOUT 200
#define TAP_THRESHOLD 0.05
#define TICK_TIMEOUT 50
#define SCROLL_THRESHOLD 0.05
#define SWIPE_THRESHOLD 0.15
#define SCALE_THRESHOLD 0.15
#define ROTATE_THRESHOLD 0.15
#define PI 3.14159265
#define NUM_AXES 4
#ifdef DEBUG_DRIVER
# define LOG_DEBUG_DRIVER LOG_DEBUG
#else
# define LOG_DEBUG_DRIVER LOG_DISABLED
#endif
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
typedef InputInfoPtr LocalDevicePtr;
#endif
/* button mapping simplified */
#define PROPMAP(m, x, y) m[x] = XIGetKnownProperty(y)
static void pointer_control(DeviceIntPtr dev, PtrCtrl *ctrl)
{
LOG_DEBUG_DRIVER("pointer_control\n");
}
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
static void init_axes_labels(Atom map[NUM_AXES])
{
memset(map, 0, NUM_AXES * sizeof(Atom));
PROPMAP(map, 0, AXIS_LABEL_PROP_REL_X);
PROPMAP(map, 1, AXIS_LABEL_PROP_REL_Y);
PROPMAP(map, 2, AXIS_LABEL_PROP_REL_VSCROLL);
PROPMAP(map, 3, AXIS_LABEL_PROP_REL_HSCROLL);
}
static void init_button_labels(Atom map[DIM_BUTTON])
{
memset(map, 0, DIM_BUTTON * sizeof(Atom));
PROPMAP(map, MT_BUTTON_LEFT, BTN_LABEL_PROP_BTN_LEFT);
PROPMAP(map, MT_BUTTON_MIDDLE, BTN_LABEL_PROP_BTN_MIDDLE);
PROPMAP(map, MT_BUTTON_RIGHT, BTN_LABEL_PROP_BTN_RIGHT);
PROPMAP(map, MT_BUTTON_WHEEL_UP, BTN_LABEL_PROP_BTN_WHEEL_UP);
PROPMAP(map, MT_BUTTON_WHEEL_DOWN, BTN_LABEL_PROP_BTN_WHEEL_DOWN);
PROPMAP(map, MT_BUTTON_HWHEEL_LEFT, BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
PROPMAP(map, MT_BUTTON_HWHEEL_RIGHT, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
/* how to map swipe buttons? */
PROPMAP(map, MT_BUTTON_SWIPE_UP, BTN_LABEL_PROP_BTN_0);
PROPMAP(map, MT_BUTTON_SWIPE_DOWN, BTN_LABEL_PROP_BTN_1);
PROPMAP(map, MT_BUTTON_SWIPE_LEFT, BTN_LABEL_PROP_BTN_2);
PROPMAP(map, MT_BUTTON_SWIPE_RIGHT, BTN_LABEL_PROP_BTN_3);
/* how to map scale and rotate? */
PROPMAP(map, MT_BUTTON_SCALE_DOWN, BTN_LABEL_PROP_BTN_4);
PROPMAP(map, MT_BUTTON_SCALE_UP, BTN_LABEL_PROP_BTN_5);
PROPMAP(map, MT_BUTTON_ROTATE_LEFT, BTN_LABEL_PROP_BTN_6);
PROPMAP(map, MT_BUTTON_ROTATE_RIGHT, BTN_LABEL_PROP_BTN_7);
}
#endif
/**
* How to handle multitouch: http://www.x.org/wiki/Development/Documentation/Multitouch/
* Howto about xinput: http://www.x.org/wiki/Development/Documentation/XorgInputHOWTO/
* Example usage: https://gitlab.com/at-home-modifier/at-home-modifier-evdev/commit/d171b3d9194581cb6ed59dbe45d6cbf009dc0eaa?view=parallel
* Patch were smooth scrolling were introduced: https://lists.x.org/archives/xorg-devel/2011-September/025835.html
* @param dev
* @param axnum
* @param label
* @param min
* @param max
* @param resolution
*/
static void init_axle_absolute(DeviceIntPtr dev, int axnum, Atom* label)
{
/* Inform server about reported range of axis values. */
xf86InitValuatorAxisStruct(dev, axnum,
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
*label,
#endif
/* minval, maxval */ NO_AXIS_LIMITS, NO_AXIS_LIMITS,
/*resolution*/ 1,
/*min res*/ 0,
/*max res*/ 1
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
/* mode */, Absolute
#endif
);
xf86InitValuatorDefaults(dev, axnum);
}
static void init_axle_relative(DeviceIntPtr dev, int axnum, Atom* label)
{
xf86InitValuatorAxisStruct(dev, axnum, *label, NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative);
xf86InitValuatorDefaults(dev, axnum);
}
static int device_init(DeviceIntPtr dev, LocalDevicePtr local)
{
struct MTouch *mt = local->private;
unsigned char btmap[DIM_BUTTON + 1] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
Atom axes_labels[NUM_AXES], btn_labels[DIM_BUTTON];
init_axes_labels(axes_labels);
init_button_labels(btn_labels);
#endif
local->fd = xf86OpenSerial(local->options);
if (local->fd < 0) {
LOG_ERROR("cannot open device %s\n", local->name);
return !Success;
}
if (mtouch_configure(mt, local->fd)) {
LOG_ERROR("cannot configure device %s\n", local->name);
return !Success;
}
xf86CloseSerial(local->fd);
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
InitPointerDeviceStruct((DevicePtr)dev,
btmap, DIM_BUTTON,
GetMotionHistory,
pointer_control,
GetMotionHistorySize(),
2);
#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 7
InitPointerDeviceStruct((DevicePtr)dev,
btmap, DIM_BUTTON,
pointer_control,
GetMotionHistorySize(),
2);
#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
InitPointerDeviceStruct((DevicePtr)dev,
btmap, DIM_BUTTON, btn_labels,
pointer_control,
GetMotionHistorySize(),
NUM_AXES, axes_labels);
#else
#error "Unsupported ABI_XINPUT_VERSION"
#endif
init_axle_absolute(dev, 0, &axes_labels[0]);
init_axle_absolute(dev, 1, &axes_labels[1]);
init_axle_relative(dev, 2, &axes_labels[2]);
init_axle_relative(dev, 3, &axes_labels[3]);
/* Always set valuator distance to 1.0 because it reported values will be
* adjusted accordingly by smooth scroll trigger.
*/
SetScrollValuator(dev, 2, SCROLL_TYPE_VERTICAL, 1.0, SCROLL_FLAG_PREFERRED);
SetScrollValuator(dev, 3, SCROLL_TYPE_HORIZONTAL, 1.0, SCROLL_FLAG_NONE);
mprops_init(&mt->cfg, local);
XIRegisterPropertyHandler(dev, mprops_set_property, NULL, NULL);
mt->timer = NULL; /* allocated later */
mt->timer_kind = 0;
mt->absolute_mode = FALSE;
return Success;
}
static int device_on(LocalDevicePtr local)
{
struct MTouch *mt = local->private;
local->fd = xf86OpenSerial(local->options);
if (local->fd < 0) {
LOG_ERROR("cannot open device\n");
return !Success;
}
if (mtouch_open(mt, local->fd)) {
LOG_ERROR("cannot grab device\n");
return !Success;
}
/*
* xf86AddEnabledDevice() will add our device's fd to the list of SIGIO handlers.
* When a SIGIO occurs, our read_input will get called.
*/
xf86AddEnabledDevice(local);
if(mt->timer != NULL)
TimerFree(mt->timer); // release any existing timer
mt->timer = NULL;
mt->timer_kind = 0;
return Success;
}
static int device_off(LocalDevicePtr local)
{
struct MTouch *mt = local->private;
xf86RemoveEnabledDevice(local);
if (mtouch_close(mt))
LOG_WARNING("cannot ungrab device\n");
xf86CloseSerial(local->fd);
if(mt->timer != NULL)
TimerFree(mt->timer); // release any existing timer
mt->timer = NULL;
mt->timer_kind = 0;
return Success;
}
static int device_close(LocalDevicePtr local)
{
return Success;
}
static void post_button(struct MTouch* mt, int button, int new_state);
void mt_timer_start(struct MTouch *mt, int kind)
{
struct Gestures* gs = &mt->gs;
mstime_t timeout; /*< Set this variable to required timeout. */
if(kind == mt->timer_kind){
LOG_DEBUG_DRIVER("Timer %i already started\n", kind);
return;
}
mt_timer_stop(mt);
switch(kind){
case MT_TIMER_DELAYED_BUTTON:
{
struct timeval delta;
timersub(&gs->button_delayed_time, &gs->time, &delta);
timeout = timertoms(&delta);
break;
}
case MT_TIMER_COASTING:
gs->move_dx = gs->move_dy = 0.0;
gs->move_type = GS_NONE;
gs->coasting_duration_left = mt->cfg.scroll_coast.duration - 1;
timeout = mt->cfg.scroll_coast.tick_ms;
break;
case MT_TIMER_ANY:
case MT_TIMER_NONE:
return; /* do nothing */
default:
LOG_INFO("Unimplemented timer, ID: %i\n", kind);
return;
}
LOG_DEBUG_DRIVER("Start timer, ID: %i with timeout: %llu\n", kind, timeout);
mt->timer = TimerSet(mt->timer, 0, timeout, mt_timer_callback, mt);
mt->timer_kind = kind;
}
void mt_timer_stop(struct MTouch *mt)
{
struct Gestures* gs = &mt->gs;
LOG_DEBUG_DRIVER("Stop timer, ID: %i\n", mt->timer_kind);
TimerCancel(mt->timer);
switch(mt->timer_kind){
case MT_TIMER_DELAYED_BUTTON:
{
int button;
button = trigger_delayed_button_uncond(gs);
post_button(mt, button, GETBIT(gs->buttons, button));
gs->move_dx = gs->move_dy = 0.0;
gs->move_type = GS_NONE;
break;
}
case MT_TIMER_COASTING:
mt->gs.scroll_speed_x = mt->gs.scroll_speed_y = 0.0;
break;
case MT_TIMER_ANY:
case MT_TIMER_NONE:
break; /* do nothing */
default:
LOG_INFO("Unimplemented timer, ID: %i\n", mt->timer_kind);
break;
}
mt->timer_kind = MT_TIMER_NONE;
}
CARD32 mt_timer_callback(OsTimerPtr timer, CARD32 time, void *arg)
{
struct MTouch *mt = arg;
struct Gestures* gs = &mt->gs;
ValuatorMask* mask = mt->valuator_mask;
switch(mt->timer_kind){
case MT_TIMER_DELAYED_BUTTON:
{
int button;
button = trigger_delayed_button_uncond(gs);
post_button(mt, button, GETBIT(gs->buttons, button));
gs->move_dx = gs->move_dy = 0.0;
gs->move_type = GS_NONE;
mt_timer_stop(mt);
break;
}
case MT_TIMER_COASTING:
{
if (gs->coasting_duration_left <= 0)
return mt_timer_stop(mt), 0;
mstime_t delta_ms;
double coasting_progress;
valuator_mask_zero(mask);
delta_ms = mt->cfg.scroll_coast.tick_ms;
if (mt->cfg.scroll_coast.ease) {
/* Calculate easing effect */
coasting_progress = 1 - gs->coasting_duration_left / (double)mt->cfg.scroll_coast.duration;
delta_ms = delta_ms - (delta_ms * coasting_progress / 2);
coasting_progress = (cos(PI * coasting_progress) + 1) / 2;
}
else
coasting_progress = gs->coasting_duration_left / (double)mt->cfg.scroll_coast.duration;
valuator_mask_set_double(mask, 2, gs->scroll_speed_y * coasting_progress * delta_ms);
valuator_mask_set_double(mask, 3, gs->scroll_speed_x * coasting_progress * delta_ms);
gs->coasting_duration_left -= delta_ms;
xf86PostMotionEventM(mt->local_dev, Relative, mask);
mt_timer_continue(mt, mt->cfg.scroll_coast.tick_ms);
break;
}
case MT_TIMER_ANY:
case MT_TIMER_NONE:
return 0; /* do nothing */
default:
LOG_INFO("Unimplemented timer id: %i\n", mt->timer_kind);
break;
}
return 0;
}
void mt_timer_start_or_stop(struct MTouch *mt, int kind)
{
if(kind < 0)
mt_timer_stop_if(mt, -kind);
else if(kind > 0)
mt_timer_start(mt, kind);
}
void mt_timer_stop_if(struct MTouch *mt, int kind)
{
if(mt->timer_kind == kind || kind == MT_TIMER_ANY || kind == -MT_TIMER_ANY)
mt_timer_stop(mt);
}
void mt_timer_continue(struct MTouch *mt, mstime_t timeout)
{
LOG_DEBUG_DRIVER("Continue timer, ID: %i with timeout: %llu\n", mt->timer_kind, timeout);
mt->timer = TimerSet(mt->timer, 0, timeout, mt_timer_callback, mt);
}
/**
* @param mt
* @return
*/
static int can_start_coasting(struct MTouch *mt)
{
struct Gestures* gs = &mt->gs;
struct MTState* ms = &mt->state;
int i;
if(mt->cfg.scroll_smooth && mt->cfg.scroll_coast.duration > 0 &&
mt->cfg.scroll_coast.duration > 0 &&
hypot_cmpf(gs->scroll_speed_x, gs->scroll_speed_y, mt->cfg.scroll_coast.min_speed) == 1)
{
foreach_bit(i, ms->touch_used) {
if (GETBIT(ms->touch[i].flags, MT_INVALID) ||
GETBIT(ms->touch[i].flags, MT_BUTTON) ||
GETBIT(ms->touch[i].flags, MT_TAP)
)
continue;
if(GETBIT(mt->state.touch[i].flags, MT_RELEASED))
return 1;
} /* foreach */
}
return 0;
}
static bitmask_t buttons_posted = 0U;
static void post_gestures(struct MTouch *mt)
{
struct Gestures* gs = &mt->gs;
int i;
const double delta = timertoms(&gs->dt);
if(mt->absolute_mode == FALSE){
if (mt->cfg.scroll_smooth){
/* Never post these buttons in smooth mode. */
CLEARBIT(gs->buttons, MT_BUTTON_WHEEL_UP);
CLEARBIT(gs->buttons, MT_BUTTON_WHEEL_DOWN);
CLEARBIT(gs->buttons, MT_BUTTON_HWHEEL_LEFT);
CLEARBIT(gs->buttons, MT_BUTTON_HWHEEL_RIGHT);
}
}
for (i = 0; i < 32; i++) {
post_button(mt, i, GETBIT(gs->buttons, i));
}
if(mt->absolute_mode == FALSE){
if (mt->cfg.scroll_smooth){
ValuatorMask* mask; mask = mt->valuator_mask;
valuator_mask_zero(mask);
if (gs->move_dx)
valuator_mask_set_double(mask, 0, gs->move_dx);
if (gs->move_dy)
valuator_mask_set_double(mask, 1, gs->move_dy);
gs->move_dx = gs->move_dy = 0.0;
/* if is any swipe */
if(gs->move_type == GS_SWIPE2 || gs->move_type == GS_SWIPE3 || gs->move_type == GS_SWIPE4){
if(gs->scroll_speed_valid)
{
/* Delta encoded in scroll_speed. */
valuator_mask_set_double(mask, 2, gs->scroll_speed_y);
valuator_mask_set_double(mask, 3, gs->scroll_speed_x);
}
gs->scroll_speed_valid = 0;
/* Start coasting here if needed. */
if(delta != 0.0 && can_start_coasting(mt)){
/* Remove delta component from scroll_speed. */
gs->scroll_speed_x /= delta;
gs->scroll_speed_y /= delta;
mt_timer_start(mt, MT_TIMER_COASTING);
}
}
xf86PostMotionEventM(mt->local_dev, Relative, mask);
} /* if smooth scroll */
else{
// mt->absolute_mode == false
if (gs->move_dx != 0.0 || gs->move_dy != 0.0)
xf86PostMotionEvent(mt->local_dev, 0, 0, 2, (int)gs->move_dx, (int)gs->move_dy);
}
}
else{
/* Give the HW coordinates to Xserver as absolute coordinates, these coordinates
* are not scaled, this is oke if the touchscreen has the same resolution as the display.
*/
xf86PostMotionEvent(mt->local_dev, 1, 0, 2,
mt->state.touch[0].x + get_cap_xmid(&mt->caps),
mt->state.touch[0].y + get_cap_ymid(&mt->caps));
}
}
static void post_button(struct MTouch* mt, int button, int new_state)
{
struct Gestures* gs = &mt->gs;
if (new_state == GETBIT(buttons_posted, button))
return;
if (new_state) {
xf86PostButtonEvent(mt->local_dev, FALSE, button+1, 1, 0, 0);
LOG_DEBUG_DRIVER("button %d down\n", button+1);
}
else {
xf86PostButtonEvent(mt->local_dev, FALSE, button+1, 0, 0, 0);
LOG_DEBUG_DRIVER("button %d up\n", button+1);
}
MODBIT(gs->buttons, button, new_state);
MODBIT(buttons_posted, button, new_state);
}
/*
* Called for each full received packet from the touchpad.
* Any xf86 input event generated by int this callback function fill be queued by
* xorg server, and fired when control return from this function.
* So to fire event as early as possible this function should return quickly.
* For delayed events we can't simply wait in this function, because it will delay
* all events generated by 'post_gestures'.
* Moreover we don't know when next input event will occur, so to guarantee proper
* timing I have to use timer.
*
* More on input event processing:
* http://www.x.org/wiki/Development/Documentation/InputEventProcessing/
*
* HowTo:
* https://www.x.org/wiki/Development/Documentation/XorgInputHOWTO/
*/
static void read_input(LocalDevicePtr local)
{
struct MTouch *mt = local->private;
int timer_kind;
mt->local_dev = local->dev;
while (mtouch_read(mt) > 0){
timer_kind = mtouch_delayed(mt);
mt_timer_start_or_stop(mt, timer_kind);
post_gestures(mt);
}
}
static int switch_mode(ClientPtr client, DeviceIntPtr dev, int mode)
{
LocalDevicePtr local = dev->public.devicePrivate;
struct MTouch *mt = local->private;
switch (mode) {
case Absolute:
mt->absolute_mode = TRUE;
LOG_INFO("switch_mode: switing to absolute mode\n");
break;
case Relative:
mt->absolute_mode = FALSE;
LOG_INFO("switch_mode: switing to relative mode\n");
break;
default:
return XI_BadMode;
}
return Success;
}
static Bool device_control(DeviceIntPtr dev, int mode)
{
LocalDevicePtr local = dev->public.devicePrivate;
switch (mode) {
case DEVICE_INIT:
LOG_INFO("device control: init\n");
return device_init(dev, local);
case DEVICE_ON:
LOG_INFO("device control: on\n");
return device_on(local);
case DEVICE_OFF:
LOG_INFO("device control: off\n");
return device_off(local);
case DEVICE_CLOSE:
LOG_INFO("device control: close\n");
return device_close(local);
default:
LOG_INFO("device control: default\n");
return BadValue;
}
}
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
static int preinit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
{
struct MTouch *mt;
mt = calloc(1, sizeof(*mt));
if (!mt)
return BadAlloc;
pInfo->private = mt;
pInfo->type_name = XI_TOUCHPAD;
pInfo->device_control = device_control;
pInfo->read_input = read_input;
pInfo->switch_mode = switch_mode;
xf86CollectInputOptions(pInfo, NULL);
xf86OptionListReport(pInfo->options);
xf86ProcessCommonOptions(pInfo, pInfo->options);
mconfig_configure(&mt->cfg, pInfo->options); // set the defaults
mt->valuator_mask = valuator_mask_new(4);
return Success;
}
#else
static InputInfoPtr preinit(InputDriverPtr drv, IDevPtr dev, int flags)
{
struct MTouch *mt;
InputInfoPtr local = xf86AllocateInput(drv, 0);
if (!local)
goto error;
mt = calloc(1, sizeof(struct MTouch));
if (!mt)
goto error;
local->name = dev->identifier;
local->type_name = XI_TOUCHPAD;
local->device_control = device_control;
local->read_input = read_input;
local->switch_mode = switch_mode;
local->private = mt;
local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
local->conf_idev = dev;
xf86CollectInputOptions(local, NULL, NULL);
xf86OptionListReport(local->options);
xf86ProcessCommonOptions(local, local->options);
mconfig_configure(&mt->cfg, local->options);
mt->vm = NULL;
local->flags |= XI86_CONFIGURED;
error:
return local;
}
#endif
static void uninit(InputDriverPtr drv, InputInfoPtr local, int flags)
{
struct MTouch *mt = local->private;
if (mt->valuator_mask)
valuator_mask_free(&mt->valuator_mask);
free(local->private);
local->private = 0;
xf86DeleteInput(local, 0);
}
/* About xorg drivers, modules:
* http://www.x.org/wiki/Development/Documentation/XorgInputHOWTO/
*/
static InputDriverRec MTRACK = {
1,
"mtrack",
NULL,
preinit,
uninit,
NULL,
0
};
static XF86ModuleVersionInfo moduleVersion = {
"mtrack",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
ABI_CLASS_XINPUT,
ABI_XINPUT_VERSION,
MOD_CLASS_XINPUT,
{0, 0, 0, 0}
};
static pointer setup(pointer module, pointer options, int *errmaj, int *errmin)
{
xf86AddInputDriver(&MTRACK, module, 0);
return module;
}
_X_EXPORT XF86ModuleData mtrackModuleData = {&moduleVersion, &setup, NULL };
================================================
FILE: examples/acer-aspire-s3.conf
================================================
Section "InputClass"
MatchIsTouchpad "on"
Identifier "Touchpads"
Driver "mtrack"
Option "Sensitivity" "0.60"
Option "FingerHigh" "5"
Option "FingerLow" "1"
Option "IgnoreThumb" "true"
Option "ThumbRatio" "70"
Option "ThumbSize" "25"
Option "IgnorePalm" "true"
Option "TapButton1" "1"
Option "TapButton2" "3"
Option "TapButton3" "0"
Option "TapButton4" "0"
Option "ClickFinger1" "3"
Option "ClickFinger2" "3"
Option "ClickFinger3" "3"
Option "ButtonMoveEmulate" "false"
Option "ButtonIntegrated" "true"
Option "ClickTime" "25"
Option "SwipeLeftButton" "8"
Option "SwipeRightButton" "9"
Option "SwipeUpButton" "0"
Option "SwipeDownButton" "0"
Option "SwipeDistance" "700"
Option "ScrollCoastDuration" "500"
Option "ScrollCoastEnableSpeed" ".8"
Option "ScrollUpButton" "4"
Option "ScrollDownButton" "5"
Option "ScrollLeftButton" "6"
Option "ScrollRightButton" "7"
Option "ScrollDistance" "75"
Option "ScrollSmooth" "1"
Option "ScrollSensitivity" "0"
Option "ScrollClickTime" "0"
Option "EdgeSize" "20"
EndSection
================================================
FILE: examples/asus-zenbook-ux330ua-ah55
================================================
# mtrack config made for asus-zenbook-ux330ua-ah55
###--------------------------------------------------------------------------###
# Properties in comments are "xinput set-prop" command to enable setting live (without restarting X)
# Refer to source code to read more about those: xf86-input-mtrack/include/mprops.h
###--------------------------------------------------------------------------###
Section "InputClass"
MatchIsTouchpad "on"
Identifier "Touchpads"
Driver "mtrack"
Option "DeviceEnabled" "1"
###--------------------------------------------------------------------------###
### http://www.x.org/wiki/Development/Documentation/PointerAcceleration/
### Base velocity setting
### Options for polynomial("2") profile
###--------------------------------------------------------------------------###
Option "AccelerationProfile" "4"
Option "Sensitivity" "0.75" # Adjusts the sensitivity (movement speed) of the touchpad. This is a real number greater than or equal to zero. Default is 1. A value of 0 will disable pointer movement.
Option "AdaptiveDeceleration" "2.0"
Option "ConstantDeceleration" "1.02"
Option "VelocityScale" "1.0"
###---------------------------------------------------------------------------###
### Ignore certain touch type
###---------------------------------------------------------------------------###
Option "PalmSize" "30" # The minimum size of what's considered a palm. Palms are expected to be very large on the trackpad. This is represented as a percentage of the maximum touch value and is dependent on the trackpad hardware. Integer value. Defaults to 40.
Option "IgnorePalm" "true" # Whether or not to ignore touches that are determined to be palms. Boolean value. Defaults to false.
Option "DisableOnPalm" "true" # Whether or not to disable the entire trackpad when a palm is touching. Boolean value. Defaults to false.
Option "IgnoreThumb" "true" # Whether or not to ignore touches that are determined to be thumbs. Boolean value. Defaults to false.
Option "ThumbRatio" "70" # The width/length ratio of what's considered a thumb. It is expected that a thumb is longer than it is wide. This tells the driver how much longer. Percentage represented by an integer. Defaults to 70.
Option "ThumbSize" "15" # The minimum size of what's considered a thumb. It is expected that a thumb will be larger than other fingers. This is represented as a percentage of the maximum touch value and is dependent on the trackpad hardware. Integer value. Defaults to 25.
###--------------------------------------------------------------------------###
### Set click interactions
###--------------------------------------------------------------------------###
Option "ButtonEnable" "true" # Whether or not to enable the physical buttons on or near the trackpad. Boolean value. Defaults to true.
Option "ButtonMoveEmulate" "true" # Whether or not to count the moving finger when emulating button clicks. Useful to disable if you use two hands on trackpad. Boolean value. Defaults to true.
Option "ButtonIntegrated" "true" # Whether or not the physical buttons are integrated with the trackpad. If you have a one-piece trackpad like on newer MacBooks, this should be set to true. Button emulation depends on this value being correct. Boolean value. Defaults to true.
Option "ButtonZonesEnable" "true" # Whether or not to enable button zones. If button zones are enabled then the trackpad will be split into one, two, or three vertical zones. Clicking the integrated button in one of these zones will send the button event for ClickFinger1, ClickFinger2, or ClickFinger3. The driver will only add zones for those ClickFinger values that are enabled. So setting ClickFinger1 to 0 and enabling the other two will create two zones, one for ClickFinger2 and one for ClickFinger3. Boolean value. Defaults to false.
Option "LimitButtonZonesToBottomEdge" "true" # Restrict button zones inside the EdgeBottom area. So instead of enabling zones on the full pad height, the zone is limited to the percentage set for the EdgeBottom. Boolean value. Default to false.
# Zones stack from left to right inside the 20% height defined above (EdgeBottomSize)
Option "FirstZoneButton" "1" # The button to emulate when the zone is pressed. This is the leftmost part of the pad. Integer value. A value of 0 disables this zone split. Defaults to 1.
Option "SecondZoneButton" "3" # The button to emulate when the zone is pressed. This will float to the right of the leftmost zone. Integer value. A value of 0 disables this zone split. Defaults to 2.
# Next one is not needed and defaut to zero
#Option "ThirdZoneButton" "0" # The button to emulate when the zone is pressed. This will float to the right of the leftmost zone. Integer value. A value of 0 disables this zone split. Defaults to 0.
Option "ClickFinger0" "1" # Which button to emulate when no valid finger placement is touching the trackpad during a click. Integer value. A value of 0 disables one-touch emulation. Defaults to 1.
Option "ClickFinger1" "1" # Which button to emulate when one finger is touching the trackpad during a click. Integer value. A value of 0 disables one-touch emulation. Defaults to 1.
Option "ClickFinger2" "3" # Which button to emulate when two fingers are touching the trackpad during a click. Integer value. A value of 0 disabled one-touch emulation. Defaults to 2.
Option "ClickFinger3" "2" # Which button to emulate when three fingers are touching the trackpad during a click. Integer value. A value of 0 disabled one-touch emulation. Defaults to 3.
###---------------------- Gesture Settings ----------------------------------###
### property: "Trackpad Gesture Settings"
Option "GestureClickTime" "20" # When a gesture triggers a click, how much time to hold down the emulated button. Integer value representing milliseconds. Defaults to 10.
Option "GestureWaitTime" "3" # Touches are allowed to transition from one gesture to another. For example, you may go from scrolling to swiping without releasing your fingers from the pad. This value is the amount of time you must be performing the new gesture before it is triggered. This prevents accidental touches from triggering other gestures. Integer value representing milliseconds. Defaults to 100.
###--------------------------------------------------------------------------###
Option "ButtonTouchExpire" "120" # How long (in ms) to consider a touching finger as part of button emulation. A value of 0 will not expire touches. Integer value. Defaults to 100.
Option "FingerLow" "0" # Defines the pressure at which a finger is detected as a release. This is a percentage represented as an integer. Default is 5.
Option "FingerHigh" "0" # Defines the pressure at which a finger is detected as a touch. This is a percentage represented as an integer. Default is 5.
###---------------------- Tap Settings --------------------------------------###
### property "Trackpad Tap Settings"
Option "ClickTime" "15" # When tapping, how much time to hold down the emulated button. Integer value representing milliseconds. Integer value representing miliseconds. Defaults to 50.
Option "MaxTapTime" "165" # The amount of time to wait for incoming touches after first one before counting it as emulated button click. Integer value representing milliseconds. Defaults to 120.
Option "MaxTapMove" "155" # How far a touch is allowed to move before counting it is no longer considered a tap. Integer value. Defaults to 400.
###--------------------------------------------------------------------------###
Option "TapButton1" "1" # Which button to emulate for one-finger tapping. Integer value. A value of 0 disables one-finger tapping. Defaults to 1.
Option "TapButton2" "3" # Which button to emulate for two-finger tapping. Integer value. A value of 0 disables two-finger tapping. Defaults to 3.
Option "TapButton3" "2" # Which button to emulate for three-finger tapping. Integer value. A value of 0 disables three-finger tapping. Defaults to 2.
#Option "TapButton4" "0" # Which button to emulate for four-finger tapping. Integer value. A value of 0 disables three-finger tapping. Defaults to 0.
###------------------------ Swipe2 as mouse wheel ---------------------------###
Option "ScrollDistance" "22" # For two finger scrolling. How far you must move your fingers before a button click is triggered. Integer value. Defaults to 150.
Option "ScrollClickTime" "12" # For two finger scrolling. How long button triggered by scrolling will be hold down. A value of 0 will hold button down till end of gesture. 0 - emit button click only once pre "instance" of gesture. Integer value representing milliseconds. Defaults to 20.
Option "ScrollSensitivity" "0" # For two finger scrolling. Sensitivity (movement speed) of pointer during two finger scrolling. A value of 0 disables pointer movement during gesture. Integer value expressed as parts per thousand of normal sensivity. A value of 1000 results with normal movement speed. Defaults to 0.
Option "ScrollUpButton" "5" # For two finger scrolling. The button that is triggered by scrolling up. Integer value. A value of 0 disables scrolling up. Defaults to 4.
Option "ScrollDownButton" "4" # For two finger scrolling. The button that is triggered by scrolling down. Integer value. A value of 0 disables scrolling down. Defaults to 5.
Option "ScrollLeftButton" "6" # For two finger scrolling. The button that is triggered by scrolling left. Integer value. A value of 0 disables scrolling left. Defaults to 6.
Option "ScrollRightButton" "7" # For two finger scrolling. The button that is triggered by scrolling right. Integer value. A value of 0 disables scrolling right. Defaults to 7.
###------------------------ Swipe3 - act as mouse wheel ---------------------###
Option "SwipeDistance" "22"
Option "SwipeClickTime" "12"
### property: "Trackpad Swipe Buttons"
Option "SwipeUpButton" "4"
Option "SwipeDownButton" "5"
Option "SwipeLeftButton" "6"
Option "SwipeRightButton" "7"
###--------------------------------------------------------------------------###
###---------------------- Swipe4 to drag buttons 9 10 11 12 -----------------###
Option "Swipe4Distance" "280"
Option "Swipe4ClickTime" "50"
Option "Swipe4Sensitivity" "0"
## property: "Trackpad Swipe4 Buttons"
Option "Swipe4UpButton" "9"
Option "Swipe4DownButton" "10"
Option "Swipe4LeftButton" "11"
Option "Swipe4RightButton" "12"
###--------------------------------------------------------------------------###
Option "ScaleDistance" "70"
Option "ScaleUpButton" "12"
Option "ScaleDownButton" "13"
Option "RotateDistance" "350"
Option "RotateLeftButton" "14"
Option "RotateRightButton" "15"
###--------------------------------------------------------------------------###
### xinput set-prop 11 "Trackpad Drag Settings" 1 350 60 200
Option "TapDragEnable" "true"
Option "TapDragTime" "350"
Option "TapDragWait" "40"
Option "TapDragDist" "150"
Option "TapDragLockTimeout" "0" # This is how long the driver will wait after initial drag in 'drag ready' state in which it will be able to resume previous drag without additional up, down sequence. Value of 0 disables this functionality. Values less than zero will make mtrack requre additional tap to finish drag by sending button up. Integer value representing milliseconds. Defaults to 500.
###--------------------------------------------------------------------------###
Option "EdgeBottomSize" "17" # Disable tap and movement detection in the bottom 17% of the pad
#Option "EdgeTopSize" "2"
#Option "EdgeLeftSize" "4"
#Option "EdgeRightSize" "6"
#Option "EdgeScrollUpButton" "4"
#Option "EdgeScrollDownButton" "5"
Option "Hold1Move1StationaryMaxMove" "120"
Option "Hold1Move1StationaryButton" "1" # For two finger hold-and-move functionality. The button that is triggered by holding one finger and moving another one. Integer value. A value of 0 disables hold-and-move. Value of 0 disables this functionality. Defaults to 1.
EndSection
================================================
FILE: examples/dell-precision-5520.conf
================================================
# Settings for Dell Precision 5520. Includes three-finger drag and reversed two finger scrolling.
Section "InputClass"
MatchIsTouchpad "on"
Identifier "Touchpads"
Driver "mtrack"
Option "DeviceEnabled" "1"
Option "AccelerationProfile" "1"
Option "Sensitivity" "1.20"
Option "ClickTime" "25"
# Tried these, didn't like them, YMMV.
# Option "AdaptiveDeceleration" "2.0"
# Option "ConstantDeceleration" "1.2"
# Option "VelocityScale" "3.0"
Option "SwipeDistance" "1"
Option "SwipeLeftButton" "1"
Option "SwipeRightButton" "1"
Option "SwipeUpButton" "1"
Option "SwipeDownButton" "1"
Option "SwipeClickTime" "0"
Option "SwipeSensitivity" "1000"
Option "ScrollDownButton" "4"
Option "ScrollUpButton" "5"
Option "ScrollDistance" "25"
Option "ScrollCoastDuration" "500"
Option "IgnorePalm" "true"
Option "IgnoreThumb" "true"
Option "ThumbSize" "25"
Option "ThumbRatio" "70"
Option "EdgeRightSize" "0"
Option "TapDragEnable" "0"
Option "Hold1Move1StationaryButton" "0"
# I hate edge scrolling.
Option "EdgeScrollDist" "2000000000"
Option "FingerHigh" "5"
Option "FingerLow" "1"
EndSection
================================================
FILE: examples/dell-xps13-9333.conf
================================================
# MatchIsTouchpad "on"
#Section "InputClass"
# Identifier "Touchpads"
# Driver "mtrack"
#EndSection
Section "InputClass"
MatchIsTouchpad "on"
Identifier "Touchpads"
Driver "mtrack"
Option "DeviceEnabled" "1"
###--------------------------------------------------------------------------###
# http://www.x.org/wiki/Development/Documentation/PointerAcceleration/
###--------------------------------------------------------------------------###
###--------------------------------------------------------------------------###
### Options for acceleration profile "0"
###--------------------------------------------------------------------------###
# some curved deceleration
### Option "AccelerationProfile" "0"
### Option "AdaptiveDeceleration" "5.5"
# linear deceleration (mouse speed reduction)
### Option "ConstantDeceleration" "1.01"
### Option "Sensitivity" "0.49"
### Option "VelocityScale" "10.0"
###--------------------------------------------------------------------------###
###--------------------------------------------------------------------------###
### Options for polynomial("2") profile
###--------------------------------------------------------------------------###
Option "AccelerationProfile" "4"
Option "Sensitivity" "0.75"
Option "AdaptiveDeceleration" "2.0"
Option "ConstantDeceleration" "1.02"
Option "VelocityScale" "1.0"
#------------------------------------------------------------------------------#
Option "PalmSize" "40"
Option "IgnorePalm" "true"
# Option "IgnoreThumb" "true"
# Option "ThumbRatio" "70"
# Option "ThumbSize" "35"
###---------------------- Gesture Settings ----------------------------------###
### property: "Trackpad Gesture Settings"
Option "GestureClickTime" "20"
Option "GestureWaitTime" "3"
###--------------------------------------------------------------------------###
Option "ButtonTouchExpire" "120"
Option "FingerLow" "0"
Option "FingerHigh" "0"
###---------------------- Tap Settings --------------------------------------###
### property "Trackpad Tap Settings"
Option "ClickTime" "35"
Option "MaxTapTime" "145"
Option "MaxTapMove" "85"
###--------------------------------------------------------------------------###
Option "TapButton1" "1"
Option "TapButton2" "2"
Option "TapButton3" "3"
###------------------------ Swipe2 as mouse wheel ---------------------------###
Option "ScrollDistance" "22"
Option "ScrollClickTime" "12"
Option "ScrollSensitivity" "0"
Option "ScrollUpButton" "4"
Option "ScrollDownButton" "5"
Option "ScrollLeftButton" "6"
Option "ScrollRightButton" "7"
###--------------------------------------------------------------------------###
###------------------------ Swipe to drag button 8 --------------------------###
Option "SwipeDistance" "1"
Option "SwipeClickTime" "0"
Option "SwipeSensitivity" "1100"
Option "SwipeUpButton" "8"
Option "SwipeDownButton" "8"
Option "SwipeLeftButton" "8"
Option "SwipeRightButton" "8"
###--------------------------------------------------------------------------###
###------------------------ Scroll to drag button 8 -------------------------###
Option "ScrollDistance" "1"
Option "ScrollClickTime" "0"
Option "ScrollSensitivity" "1100"
Option "ScrollUpButton" "8"
Option "ScrollDownButton" "8"
Option "ScrollLeftButton" "8"
Option "ScrollRightButton" "8"
###--------------------------------------------------------------------------###
###------------------------ Swipe3 - act as mouse wheel ---------------------###
Option "SwipeDistance" "22"
Option "SwipeClickTime" "12"
Option "ScrollSensitivity" "0"
### property: "Trackpad Swipe Buttons"
Option "SwipeUpButton" "4"
Option "SwipeDownButton" "5"
Option "SwipeLeftButton" "6"
Option "SwipeRightButton" "7"
###--------------------------------------------------------------------------###
###---------------------- Swipe4 to drag buttons 9 10 11 12 -----------------###
Option "Swipe4Distance" "280"
Option "Swipe4ClickTime" "50"
Option "Swipe4Sensitivity" "0"
## property: "Trackpad Swipe4 Buttons"
Option "Swipe4UpButton" "9"
Option "Swipe4DownButton" "10"
Option "Swipe4LeftButton" "11"
Option "Swipe4RightButton" "12"
###--------------------------------------------------------------------------###
###---------------------------- Swipe4 to drag button 1 ---------------------###
Option "Swipe4Distance" "1"
Option "Swipe4ClickTime" "0"
Option "Swipe4Sensitivity" "1350"
## property: "Trackpad Swipe4 Buttons"
Option "Swipe4UpButton" "1"
Option "Swipe4DownButton" "1"
Option "Swipe4LeftButton" "1"
Option "Swipe4RightButton" "1"
###--------------------------------------------------------------------------###
Option "ScaleDistance" "70"
Option "ScaleUpButton" "12"
Option "ScaleDownButton" "13"
Option "RotateDistance" "350"
Option "RotateLeftButton" "14"
Option "RotateRightButton" "15"
Option "ButtonEnable" "true"
Option "ButtonIntegrated" "true"
Option "ButtonZonesEnable" "true"
Option "ClickFinger1" "1"
Option "ClickFinger2" "2"
Option "ClickFinger3" "3"
###--------------------------------------------------------------------------###
### xinput set-prop 11 "Trackpad Drag Settings" 1 350 60 200
Option "TapDragEnable" "true"
Option "TapDragTime" "350"
Option "TapDragWait" "40"
Option "TapDragDist" "150"
###--------------------------------------------------------------------------###
Option "EdgeBottomSize" "5" # dont count touches from bottom 5% of area
Option "EdgeTopSize" "2"
Option "EdgeLeftSize" "4"
Option "EdgeRightSize" "6"
Option "EdgeScrollUpButton" "4"
Option "EdgeScrollDownButton" "5"
Option "Hold1Move1StationaryMaxMove" "90"
EndSection
================================================
FILE: examples/lenovo-710s.conf
================================================
Section "InputClass"
MatchIsTouchpad "true"
Identifier "Touchpads"
Driver "mtrack"
Option "MaxTapTime" "400"
Option "MaxTapMove" "20"
Option "ScrollDistance" "55"
Option "ScrollSmooth" "1"
Option "ScrollCoastDuration" "360"
Option "ScrollCoastEnableSpeed" "0.3"
Option "AccelerationProfile" "3"
Option "VelocityScale" "1.3"
Option "Sensitivity" "0.8"
Option "ScrollUpButton" "5"
Option "ScrollDownButton" "4"
Option "SwipeDistance" "300"
Option "Hold1Move1StationaryMaxMove" "50"
Option "TapDragDist" "400"
Option "GestureWaitTime" "20"
Option "ButtonZonesEnable" "true"
Option "ClickFinger1" "1"
Option "ClickFinger2" "3"
Option "ClickFinger3" "0"
Option "SwipeClickTime" "60"
Option "SwipeDistance" "200"
Option "SwipeUpButton" "16"
Option "SwipeDownButton" "17"
Option "Swipe4UpButton" "18"
Option "Swipe4DownButton" "19"
Option "Swipe4LeftButton" "20"
Option "Swipe4RightButton" "21"
Option "Swipe4Distance" "300"
Option "EdgeLeftSize" "4"
Option "EdgeRightSize" "7"
Option "EdgeTopSize" "0"
Option "EdgeBottomSize" "15"
EndSection
================================================
FILE: examples/lenovo-yoga-2-pro.conf
================================================
## Works pretty well on Ubuntu 18.04 with deepin DE & Xfce
########### 1. Install the mtrack driver ################
#cd /tmp
#git clone https://github.com/p2rkw/xf86-input-mtrack.git
#cd xf86-input-mtrack
#./configure --with-xorg-module-dir=/usr/lib/xorg/modules
#make
#sudo make install
########### 2. Copy this file to /usr/share/X11/xorg.conf.d/99-mtrack.conf ################
# precedence should be higher than synaptics and/or libinput (so not necessarily 99).
########### 3. I recommend using this together with dispad, to disable the touchpad while typing #############
## 1. install dependencies for dispad
#sudo apt install libconfuse-dev libxi-dev
#cd /tmp
#git clone https://github.com/BlueDragonX/dispad.git #installation will fail if you have autocrlf=true in your gitconf
#cd dispad
#./configure
#make
#sudo make install
## 2. launch dispad from terminal >dispad
## 3. configure config file >gedit ~/.dispad like so:
# # default dispad config file
# # name of the property used to enable/disable the trackpad
# property = "Trackpad Disable Input"
# # the value used to enable the trackpad
# enable = 0
# # the value used to disable the trackpad
# disable = 3
# # whether or not modifier keys disable the trackpad
# modifiers = false
# # how long (in ms) to sleep between keyboard polls
# poll = 44
# # how long (in ms) to disable the trackpad after a keystroke
# delay = 500
## 4. edit bashrc to launch dispad at terminal-startup
# echo -e "\n#Turn off touchpad upon keypress\ndispad\n" >> ~/.bashrc
# alternatively, you can start the daemon via putting this line in ~/.profile
# this profile option has the advantage of working straight from the beginning. However, it throws a warning (without consequences) after login.
Section "InputClass"
MatchIsTouchpad "on"
Identifier "Touchpads"
Driver "mtrack"
Option "DeviceEnabled" "1"
# ----- Acceleration --- most important part! ---
Option "AccelerationProfile" "2" # 2 is polynomial, recommended as "very usable"; see https://www.x.org/wiki/Development/Documentation/PointerAcceleration/#Introduction
Option "AdaptiveDeceleration" "3.5" #"if you like the speed but need some more control at pixel-level, you should set ?AdaptiveDeceleration to 2 or more."(www.x.org)
# Option "ConstantDeceleration" "1.02"
Option "VelocityScale" "4"
# ---- Basic setup
# Option "TrackPadDisable" "0" # dont disable trackpad
# Option "ButtonEnable" "true" # enable physical buttons
# Option "ButtonIntegrated" "true" # Y2p has a 1-piece pad
# ---- Responsiveness
Option "Sensitivity" "0.3" # how fast does the mouse move
Option "FingerLow" "15" # more than 10% pressure --> is a touch
Option "FingerHigh" "15" # less than 10% pressure --> not a touch
Option "IgnoreThumb" "true" # don't use thumb touches
Option "IgnorePalm" "true" # don't use palm touches
Option "DisableOnThumb" "true" # Disable complete pad once thumb detected
Option "DisableOnPalm" "true" # ...same for palm
Option "PalmSize" "30" # 30 is still a bit jumpy, but less results in bad detection of fingers
# Option "ThumbSize" "15" # Thumb is 25% of trackpad-max
# Option "ThumbRatio" "40" # thumb is 70% longer than wide
# ---- Zones (I don't really understand zones)
# Option "ButtonZonesEnable" "true" # Split pad in zones for clicks
# Option "FirstZoneButton" "1"
# Option "SecondZoneButton" "0"
# Option "ThirdZoneButton" "3"
# Option "LimitButtonZonesToBottomEdge" "false"
# ---- Physical Clicks
# Option "ClickFinger0" "0"
# Option "ClickFinger1" "1"
# Option "ClickFinger2" "0"
# Option "ClickFinger3" "0"
# ---- Tap-to-click
# Option "TapButton 1" "1" #left click on 1-finger tap
# Option "TapButton 2" "3" #right click on 2-finger tap
# Option "TapButton 3" "0" #no click on 3-finger tap
# Option "TapButton 4" "0" #no click on 4-finger tap
# ---- 2-finger Scrolling
# Option "ScrollDistance" "150" # how far to move fingers before scrolling starts (unit?)
# Option "ScrollClickTime" "0" # how long (in ms) to press "scroll" - 0=only as long as fingers move
# Option "ScrollSensitivity" "0" # how fast to move pointer during scrolling (0=not at all)
# Option "ScrollSmooth" "1" # High precision smooth scrolling
# Option "ScrollCoastDuration" "100" # how long to move screen after finger movement (in ms)
# Option "ScrollCoastEnableSpeed" ".3" #
# ---- 3/4-finger Swiping
# I never use that, so I set a threshold so high, it won't be used
# Option "SwipeDistance" "9999"
# Option "SwipeUpButton" "0"
# Option "SwipeDownButton" "0"
# Option "SwipeLeftButton" "0"
# Option "SwipeRightButton" "0"
# Option "Swipe4Distance" "9999"
# Option "Swipe4UpButton" "0"
# Option "Swipe4DownButton" "0"
# Option "Swipe4LeftButton" "0"
# Option "Swipe4RightButton" "0"
# ---- Edge scrolling
# I never use that, so I set a threshold so high, it won't be used
# Option "EdgeScrollDist" "9999"
# Option "EdgeScrollUpButton" "0"
# Option "EdgeScrollDownButton" "0"
# Option "EdgeScrollLeftButton" "0"
# Option "EdgeScrollRightButton" "0"
# ---- Pinch zoom
# Option "ScaleDistance" "100" # how far to move fingers? (unit?)
# Option "ScaleUpButton" "12"
# Option "ScaleDownButton" "13"
# ---- 2 finger rotation
# I never use that, so I set a threshold so high, it won't be used
# Option "RotateDistance" "9999" # how far to move fingers? (unit?)
# Option "RotateLeftButton" "0"
# Option "RotateRightButton" "0"
# ---- highlight text with holding one and moving another finger
# Option "Hold1Move1StationaryButton" "1" # left-mouse click = 1
# Option "Hold1Move1StationaryMaxMove" "90" # threshold for how far 2nd finger can be moved (unit?)
# ---- tap to drag
# Option "TapDragEnable" "true"
# Option "TapDragWait" "60"
# Option "TapDragTime" "300" # how long after tap does the driver wait for drag (in ms)?
# Option "TapDragDist" "200" # threshold, after this dist it's seen as mousemove not as drag (unit?)
# ---- Invert axes for mousemovement (not scrolling!)
# Option "AxisXInvert" "false"
# Option "AxisYInvert" "false"
# ---- Natural Scrolling (uncommenting will disable it, as default buttons are reversed)
Option "ScrollDownButton" "4"
Option "ScrollUpButton" "5"
Option "ScrollLeftButton" "7"
Option "ScrollRightButton" "6"
EndSection
================================================
FILE: examples/macbook-pro-retina-2013.conf
================================================
Section "InputClass"
MatchIsTouchpad "on"
Identifier "Touchpads"
MatchDevicePath "/dev/input/event*"
Driver "mtrack"
# The faster you move, the more distance pointer will travel, using "polynomial" profile
Option "AccelerationProfile" "2"
# Tweak cursor movement speed with this
Option "Sensitivity" "0.05"
# Pressure at which a finger is detected as a touch
Option "FingerHigh" "1"
# Pressure at which a finger is detected as a release
Option "FingerLow" "1"
# I often use thumb to press down the physical button, so let's not ignore it
Option "IgnoreThumb" "false"
Option "ThumbRatio" "70"
Option "ThumbSize" "23"
# Ignore palm, with palm takes up to 30% of your touch pad
Option "IgnorePalm" "true"
Option "PalmSize" "30"
# Trigger mouse button when tap: 1 finger - left click, 2 finger - right click, 3 - middle click
Option "TapButton1" "1"
Option "TapButton2" "3"
Option "TapButton3" "2"
Option "TapButton4" "0"
Option "ClickTime" "1"
# Disable tap-to-drag, we're using three finger drag instead
Option "TapDragEnable" "false"
# While touching the touch pad with # fingers, press the touchpad physical click button
Option "ClickFinger1" "1"
Option "ClickFinger2" "3"
Option "ClickFinger3" "2"
Option "ButtonMoveEmulate" "false"
Option "ButtonIntegrated" "true"
# The momentum after scroll fingers released
Option "ScrollCoastDuration" "300"
Option "ScrollCoastEnableSpeed" ".1"
# Natural scrolling with two fingers
Option "ScrollSmooth" "true"
Option "ScrollUpButton" "5"
Option "ScrollDownButton" "4"
Option "ScrollLeftButton" "7"
Option "ScrollRightButton" "6"
# Tweak scroll sensitivity with ScrollDistance, don't touch ScrollSensitivity
Option "ScrollDistance" "270"
Option "ScrollClickTime" "1"
# Three finger drag
Option "SwipeDistance" "1"
Option "SwipeLeftButton" "1"
Option "SwipeRightButton" "1"
Option "SwipeUpButton" "1"
Option "SwipeDownButton" "1"
Option "SwipeClickTime" "1"
Option "SwipeSensitivity" "1500"
# Four finger swipe, 8 & 9 are for browsers navigating back and forth respectively
Option "Swipe4LeftButton" "9"
Option "Swipe4RightButton" "8"
# Mouse button >= 10 are not used by Xorg, so we'll map them with xbindkeys and xdotool later
Option "Swipe4UpButton" "11"
Option "Swipe4DownButton" "10"
# Mouse buttons triggered by 2-finger pinching gesture
Option "ScaleDistance" "300"
Option "ScaleUpButton" "12"
Option "ScaleDownButton" "13"
# Mouse buttons trigger by 2-finger rotating gesture, disabled to enhance the pinch gesture
Option "RotateLeftButton" "0"
Option "RotateRightButton" "0"
Option "TabDragEnable" "false"
Option "GestureClickTime" "1"
Option "GestureWaitTime" "0"
EndSection
================================================
FILE: examples/macbook.conf
================================================
# Taken from: https://howchoo.com/g/mdy0ngziogm/the-perfect-almost-touchpad-settings-on-linux-2
Section "InputClass"
MatchIsTouchpad "on"
Identifier "Touchpads"
Driver "mtrack"
Option "Sensitivity" "0.60"
Option "FingerHigh" "5"
Option "FingerLow" "1"
Option "IgnoreThumb" "true"
Option "ThumbRatio" "70"
Option "ThumbSize" "25"
Option "IgnorePalm" "true"
Option "TapButton1" "0"
Option "TapButton2" "0"
Option "TapButton3" "0"
Option "TapButton4" "0"
Option "ClickFinger1" "3"
Option "ClickFinger2" "3"
Option "ClickFinger3" "3"
Option "ButtonMoveEmulate" "false"
Option "ButtonIntegrated" "true"
Option "ClickTime" "25"
Option "BottomEdge" "30"
Option "SwipeLeftButton" "8"
Option "SwipeRightButton" "9"
Option "SwipeUpButton" "0"
Option "SwipeDownButton" "0"
Option "SwipeDistance" "700"
Option "ScrollCoastDuration" "500"
Option "ScrollCoastEnableSpeed" ".3"
Option "ScrollUpButton" "5"
Option "ScrollDownButton" "4"
Option "ScrollLeftButton" "7"
Option "ScrollRightButton" "6"
Option "ScrollDistance" "350"
Option "Hold1Move1StationaryButton" "0"
EndSection
================================================
FILE: include/button.h
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifndef BUTTON_H
#define BUTTON_H
#define DIM_BUTTON 15
#define MT_BUTTON_LEFT 0
#define MT_BUTTON_MIDDLE 1
#define MT_BUTTON_RIGHT 2
#define MT_BUTTON_WHEEL_UP 3
#define MT_BUTTON_WHEEL_DOWN 4
#define MT_BUTTON_HWHEEL_LEFT 5
#define MT_BUTTON_HWHEEL_RIGHT 6
#define MT_BUTTON_SWIPE_UP 7
#define MT_BUTTON_SWIPE_DOWN 8
#define MT_BUTTON_SWIPE_LEFT 9
#define MT_BUTTON_SWIPE_RIGHT 10
#define MT_BUTTON_SCALE_DOWN 11
#define MT_BUTTON_SCALE_UP 12
#define MT_BUTTON_ROTATE_LEFT 13
#define MT_BUTTON_ROTATE_RIGHT 14
#endif
================================================
FILE: include/capabilities.h
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifndef CAPABILITIES_H
#define CAPABILITIES_H
#include "common.h"
#include "button.h"
struct Capabilities {
struct input_id devid;
char devname[128];
int has_left, has_middle, has_right;
int has_mtdata, has_ibt;
int has_slot;
int has_abs[MT_ABS_SIZE];
struct input_absinfo slot;
struct input_absinfo abs[MT_ABS_SIZE];
};
int read_capabilities(struct Capabilities *cap, int fd);
int get_cap_xsize(const struct Capabilities *cap);
int get_cap_ysize(const struct Capabilities *cap);
int get_cap_wsize(const struct Capabilities *cap);
int get_cap_xmid(const struct Capabilities *cap);
int get_cap_ymid(const struct Capabilities *cap);
int translate_cap_x(const struct Capabilities *cap, int x);
int translate_cap_y(const struct Capabilities *cap, int y);
int get_cap_xmin(const struct Capabilities *cap);
int get_cap_ymin(const struct Capabilities *cap);
void output_capabilities(const struct Capabilities *cap);
#endif
================================================
FILE: include/common.h
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifndef COMMON_H
#define COMMON_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <xorg-server.h>
#include <xf86.h>
#include <xf86_OSproc.h>
#include <xf86Xinput.h>
#include <errno.h>
#include <mtdev-mapping.h>
#include <stdint.h>
#include <sys/time.h>
#define DIM_FINGER 16
#define DIM_TOUCHES 16
/* year-proof millisecond event time */
typedef __u64 mstime_t;
/* all bit masks have this type */
typedef unsigned int bitmask_t;
/**
* m - bit set (integer)
* x - modified bit
* b - new value
* @{
*/
#define BITMASK(x) (1U << (x))
#define BITONES(x) (BITMASK(x) - 1U)
#define GETBIT(m, x) (((m) >> (x)) & 1U)
#define SETBIT(m, x) (m |= BITMASK(x))
#define CLEARBIT(m, x) (m &= ~BITMASK(x))
#define MODBIT(m, x, b) ((b) ? SETBIT(m, x) : CLEARBIT(m, x))
/** }@ */
#define ABSVAL(x) ((x) < 0 ? -1*(x) : (x))
#define MINVAL(x, y) ((x) < (y) ? (x) : (y))
#define MAXVAL(x, y) ((x) > (y) ? (x) : (y))
#define MODVAL(x, y) ((x) - ((int)((x) / (y))) * (y))
#define SQRVAL(x) ((x) * (x))
#define CLAMPVAL(x, min, max) MAXVAL(MINVAL(x, max), min)
#define SGNVAL (x) ((x) < 0 ? -1 : (((x) > 0) ? 1 : 0))
#define LOG_ERROR(...) \
do{ \
xf86Msg(X_ERROR, "mtrack[%i] %s:%i: ", get_next_log_number(), __FILE__, __LINE__); \
xf86Msg(X_ERROR, __VA_ARGS__); \
}while(0)
#define LOG_WARNING(...) \
do{ \
xf86Msg(X_WARNING, "mtrack[%i] %s:%i: ", get_next_log_number(), __FILE__, __LINE__); \
xf86Msg(X_WARNING, __VA_ARGS__); \
}while(0)
#define LOG_INFO(...) \
do{ \
xf86Msg(X_INFO, "mtrack[%i] %s:%i: ", get_next_log_number(), __FILE__, __LINE__); \
xf86Msg(X_INFO, __VA_ARGS__); \
}while(0)
#define LOG_INFO_CONT(...) xf86Msg(X_INFO, "mtrack[...]: " __VA_ARGS__)
#define LOG_DISABLED(...) do { } while(0)
#define LOG_INFO_ENABLED(...) LOG_INFO(__VA_ARGS__)
#define LOG_INFO_DISABLED(...)
#define LOG_INFO2(ENABLED_or_DISABLED, ...) LOG_INFO_##ENABLED_or_DISABLED(__VA_ARGS__)
#if defined(DEBUG_DRIVER) && (DEBUG_DRIVER != 0)
# define LOG_DEBUG LOG_INFO
#else
# define LOG_DEBUG LOG_DISABLED
#endif
static inline int get_next_log_number(){
static int last = 0;
return ++last;
}
/* Retrieve the current time and place it in tv.
*/
static inline void microtime(struct timeval* tv)
{
gettimeofday(tv, NULL);
}
/* Copy one time value to another.
*/
static inline void timercp(struct timeval* dest, const struct timeval* src)
{
memcpy(dest, src, sizeof(struct timeval));
}
/* Convert a timeval to milliseconds since the epoch. Truncates additional
* timer resolution effectively rounding down.
*/
static inline mstime_t timertoms(const struct timeval* tv)
{
return (mstime_t)(tv->tv_sec*1000) + (mstime_t)(tv->tv_usec/1000);
}
/* Convert a value in milliseconds to a timeval and place the value in tv.
*/
static inline void timerfromms(struct timeval* tv, const mstime_t ms)
{
tv->tv_sec = (time_t)(ms/1000);
tv->tv_usec = (suseconds_t)((ms%1000)*1000);
}
/* Convert a timeval to microseconds.
*/
static inline suseconds_t timertomicro(const struct timeval* tv)
{
return tv->tv_sec * 1000000 + tv->tv_usec;
}
/* Add milliseconds to a timeval and place the resulting value in dest.
*/
static inline void timeraddms(const struct timeval* a, const mstime_t b, struct timeval* dest)
{
struct timeval tv;
timerfromms(&tv, b);
timeradd(a, &tv, dest);
}
/* Check if given timeval a is set to epoch time.
*/
static inline int isepochtime(const struct timeval* a)
{
struct timeval epoch;
timerclear(&epoch);
return timercmp(a, &epoch, ==);
}
/* Clamp value to 15 bits.
*/
static inline int clamp15(int x)
{
return x < -32767 ? -32767 : x > 32767 ? 32767 : x;
}
/* Absolute scale is assumed to fit in 15 bits.
*/
static inline int dist2(int dx, int dy)
{
dx = clamp15(dx);
dy = clamp15(dy);
return dx * dx + dy * dy;
}
/* Count number of bits (Sean Eron Andersson's Bit Hacks).
*/
static inline int bitcount(unsigned v)
{
v -= ((v>>1) & 0x55555555);
v = (v&0x33333333) + ((v>>2) & 0x33333333);
return (((v + (v>>4)) & 0xF0F0F0F) * 0x1010101) >> 24;
}
/* Return index of first bit [0-31], -1 on zero\
*/
#define firstbit(v) (__builtin_ffs(v) - 1)
/* Boost-style foreach bit.
*/
#define foreach_bit(i, m) \
for (i = firstbit(m); i >= 0; i = firstbit((m) & (~0U << (i + 1))))
/* Robust system ioctl calls.
*/
#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
/**
* \defgroup Gestures.c Functions from gestures.c
*
* These functions are implemented in gestures.c
*
* @{
*/
struct Gestures;
/**
* Compute x*x+y*y and compare it with value*value.
* It's equal to following comparision: sqrt(x*x+y*y) [?] value.
* Implementation in gestures.c
*
* @param x
* @param y
* @param value
* @return -1 when lhs is less than rhs, 0 when equal, 1 when greater
*/
int hypot_cmpf(double x, double y, double value);
/**
* It's called 'uncond' because caller have to check that all conditions required to
* trigger delayed button were met.
*
* @return triggered button
*/
int trigger_delayed_button_uncond(struct Gestures* gs);
/** }@ */
#endif
================================================
FILE: include/gestures.h
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
* Copyright (C) 2015-2018 Paweł Turkowski <p2rkw0@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifndef GESTURES_H
#define GESTURES_H
#include "common.h"
#include "mconfig.h"
#include "hwstate.h"
#include "mtstate.h"
struct MTouch;
#define GS_NONE 0
#define GS_MOVE 1
#define GS_SCROLL 2
#define GS_SWIPE2 GS_SCROLL
#define GS_SWIPE3 3
#define GS_SWIPE4 4
#define GS_SCALE 5
#define GS_ROTATE 6
#define GS_DRAG_READY 7
#define GS_DRAG_WAIT 8
#define GS_DRAG_ACTIVE 9
#define GS_HOLD1_MOVE1 10
#define GS_HOLD1_MOVE2 11
#define GS_HOLD1_MOVE3 12
struct Gestures {
/* Taps, physical buttons, and gestures will trigger
* button events. If a bit is set, the button is down.
* If a bit is not set, the button is up.
* Bit 0 is button 1.
*/
bitmask_t buttons;
/* Pointer movement is tracked here.
*/
double move_dx, move_dy;
/* Current time and time delta. Updated after each event and after sleeping.
*/
struct timeval time;
struct timeval dt;
/* Internal state tracking. Not for direct access.
*/
/** Lastly emulated button, by pressing integrated button. */
int button_emulate;
int integrated_emulated_button;
/* Invalid button_delayed means that there's no delayed button.
*/
int button_delayed;
/* If equals to epoch time then button is delayed till gesture end.
*/
struct timeval button_delayed_time;
int tap_touching;
int tap_released;
struct timeval tap_timeout;
int move_type;
double move_dist;
int move_dir;
int drag_state;
int move_drag_dx;
int move_drag_dy;
struct timeval move_wait;
struct timeval move_drag_wait;
struct timeval move_drag_expire;
struct timeval move_start;
/* Scroll vertical, horizontal.
*/
double scroll_speed_x, scroll_speed_y;
int scroll_speed_valid;
/* Duration left */
int coasting_duration_left;
};
void gestures_init(struct MTouch* mt);
void gestures_extract(struct MTouch* mt);
int gestures_delayed(struct MTouch* mt);
static int buttons_zone_update(
struct Gestures* gs,
const struct MConfig* cfg,
const struct MTState* ms,
int lowest);
static void touch_detect_update(
struct Gestures* gs,
const struct MConfig* cfg,
const struct MTState* ms,
int latest);
#endif
================================================
FILE: include/hwstate.h
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifndef HWSTATE_H
#define HWSTATE_H
#include "common.h"
#include "capabilities.h"
struct FingerState {
/* The size of the contact area */
int touch_major, touch_minor;
/* The size of the approaching tool */
int width_major, width_minor;
int orientation, pressure;
int position_x, position_y;
int tracking_id;
};
struct HWState {
struct FingerState data[DIM_FINGER];
bitmask_t used;
bitmask_t slot;
bitmask_t button;
int max_x, max_y;
struct timeval evtime;
};
void hwstate_init(struct HWState *s,
const struct Capabilities *caps);
int hwstate_modify(struct HWState *s,
struct mtdev *dev, int fd,
const struct Capabilities *caps);
void hwstate_output(const struct HWState *s);
int find_finger(const struct HWState *s, int tracking_id);
#endif
================================================
FILE: include/mconfig.h
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifndef MCONFIG_H
#define MCONFIG_H
#include "capabilities.h"
#define DEFAULT_TRACKPAD_DISABLE 0
#define DEFAULT_TOUCH_DOWN 5
#define DEFAULT_TOUCH_UP 5
#define DEFAULT_IGNORE_THUMB 0
#define DEFAULT_IGNORE_PALM 0
#define DEFAULT_DISABLE_ON_THUMB 0
#define DEFAULT_DISABLE_ON_PALM 0
#define DEFAULT_THUMB_RATIO 70
#define DEFAULT_THUMB_SIZE 25
#define DEFAULT_PALM_SIZE 40
#define DEFAULT_EDGE_LEFT_SIZE 0
#define DEFAULT_EDGE_RIGHT_SIZE 0
#define DEFAULT_EDGE_TOP_SIZE 0
#define DEFAULT_EDGE_BOTTOM_SIZE 10
#define DEFAULT_BUTTON_ENABLE 1
#define DEFAULT_BUTTON_INTEGRATED 1
#define DEFAULT_BUTTON_ZONES 0 /* Button zones are disabled */
#define DEFAULT_IS_BUTTON_ZONES_HEIGHT_LIMITED 0 /* Button zones are emulated on the whole pad (Not limited to the bottom edge)*/
#define DEFAULT_BUTTON_FIRST_ZONE 1
#define DEFAULT_BUTTON_SECOND_ZONE 2
#define DEFAULT_BUTTON_THIRD_ZONE 0
#define DEFAULT_BUTTON_0TOUCH 0 /* "invalid" finger placement do not emulate any button */
#define DEFAULT_BUTTON_1TOUCH 1
#define DEFAULT_BUTTON_2TOUCH 2
#define DEFAULT_BUTTON_3TOUCH 3
#define DEFAULT_BUTTON_MOVE 1
#define DEFAULT_BUTTON_EXPIRE 100
#define DEFAULT_TAP_1TOUCH 1
#define DEFAULT_TAP_2TOUCH 3
#define DEFAULT_TAP_3TOUCH 2
#define DEFAULT_TAP_4TOUCH 0
#define DEFAULT_TAP_TIMEOUT 120
#define DEFAULT_TAP_HOLD 50
#define DEFAULT_TAP_DIST 400
#define DEFAULT_GESTURE_HOLD 10
#define DEFAULT_GESTURE_WAIT 100
#define DEFAULT_SCROLL_DIST 150
#define DEFAULT_SCROLL_UP_BTN 4
#define DEFAULT_SCROLL_DN_BTN 5
#define DEFAULT_SCROLL_LT_BTN 6
#define DEFAULT_SCROLL_RT_BTN 7
#define DEFAULT_SCROLL_HOLD 20
#define DEFAULT_SCROLL_COAST_MIN_SPEED 0.1f
#define DEFAULT_SCROLL_COAST_DURATION 200
#define DEFAULT_SCROLL_COAST_TICK_MS 30 /* Schould be configurable? */
#define DEFAULT_SCROLL_COAST_NO_BOOST 0
#define DEFAULT_SCROLL_COAST_EASE 0
#define DEFAULT_SWIPE_DIST 700
#define DEFAULT_SWIPE_UP_BTN 8
#define DEFAULT_SWIPE_DN_BTN 9
#define DEFAULT_SWIPE_LT_BTN 10
#define DEFAULT_SWIPE_RT_BTN 11
#define DEFAULT_SWIPE_HOLD 300
#define DEFAULT_SWIPE4_DIST 700
#define DEFAULT_SWIPE4_UP_BTN 0
#define DEFAULT_SWIPE4_DN_BTN 0
#define DEFAULT_SWIPE4_LT_BTN 0
#define DEFAULT_SWIPE4_RT_BTN 0
#define DEFAULT_SWIPE_SENS 0
#define DEFAULT_EDGE_SCROLL_DIST (DEFAULT_SCROLL_DIST*0.7)
#define DEFAULT_SCALE_DIST 150
#define DEFAULT_SCALE_UP_BTN 12
#define DEFAULT_SCALE_DN_BTN 13
#define DEFAULT_ROTATE_DIST 150
#define DEFAULT_ROTATE_LT_BTN 14
#define DEFAULT_ROTATE_RT_BTN 15
#define DEFAULT_HOLD1_MOVE1_STATIONARY_BTN 1
#define DEFAULT_HOLD1_MOVE1_STATIONARY_MAX_MOVE 20
#define DEFAULT_HOLD1_MOVE1_DIST 1
#define DEFAULT_HOLD1_MOVE1_HOLD 0
#define DEFAULT_HOLD1_MOVE1_SENS 1000
#define DEFAULT_HOLD1_MOVE1_BTN 1
#define DEFAULT_HOLD1_MOVE2_STATIONARY_BTN 3
#define DEFAULT_HOLD1_MOVE2_STATIONARY_MAX_MOVE 30
#define DEFAULT_HOLD1_MOVE2_DIST 1
#define DEFAULT_HOLD1_MOVE2_HOLD 0
#define DEFAULT_HOLD1_MOVE2_SENS 1000
#define DEFAULT_HOLD1_MOVE2_BTN 3
#define DEFAULT_HOLD1_MOVE3_STATIONARY_BTN 10
#define DEFAULT_HOLD1_MOVE3_STATIONARY_MAX_MOVE 60
#define DEFAULT_HOLD1_MOVE3_DIST 100
#define DEFAULT_HOLD1_MOVE3_HOLD 50
#define DEFAULT_HOLD1_MOVE3_SENS 0
#define DEFAULT_HOLD1_MOVE3_BTN 11
#define DEFAULT_DRAG_ENABLE 1
#define DEFAULT_DRAG_TIMEOUT 350
#define DEFAULT_DRAG_WAIT 40
#define DEFAULT_DRAG_DIST 200
#define DEFAULT_DRAG_LOCK_TIMEOUT 500
#define DEFAULT_AXIS_X_INVERT 0
#define DEFAULT_AXIS_Y_INVERT 0
#define DEFAULT_SENSITIVITY 1.0
#define DEFAULT_SCROLL_HIGH_PREC 1
#define MCFG_NONE 0
#define MCFG_SCALE 1
#define MCFG_SIZE 2
#define MCFG_PRESSURE_SIZE 3
#define MCFG_SIZE_PRESSURE 4 /* same capabilities as above, but with higher resolution of touches*/
#define MCFG_PRESSURE 5
struct MConfig {
/* Used by MTState */
// Set by caps.
int touch_type; // How to determine touch? 0 for none, 1 for scale, 2 for size, 3 for pressure
int touch_minor; // Does the touchpad report touches as ellipses? 0 or 1
int touch_min; // Minimum touch value.
int touch_max; // Maximum touch value.
int pressure_min; // Minimum pressure value.
int pressure_max; // Maximum pressure value.
int pad_width; // Width of the touchpad.
int pad_height; // Height of the touchpad.
// Set by config.
int touch_down; // When is a finger touching? 0 - 100 (percentage)
int touch_up; // When is a finger released? 0 - 100 (percentage)
int ignore_thumb; // Whether or not to ignore thumbs. 0 or 1
int ignore_palm; // Whether or not to ignore palms. 0 or 1
int disable_on_thumb; // Disable the touchpad if thumb detected. 0 or 1
int disable_on_palm; // Disable the touchpad if palm detected. 0 or 1
int thumb_ratio; // Ratio of width to length that makes a touch a thumb. 0 - 100
int thumb_size; // Minimum touch size for a thumb. 0 - 100
int palm_size; // Minimum touch size for a palm. 0 - 100
int edge_left_size; // Percent of left edge of trackpad to ignore for new touches. 0 - 100
int edge_right_size; // Percent of right edge of trackpad to ignore for new touches. 0 - 100
int edge_top_size; // Percent of top edge of trackpad to ignore for new touches. 0 - 100
int edge_bottom_size; // Percent of bottom edge of trackpad to ignore for new touches. 0 - 100
int axis_x_invert; // Whether or not to invert the x axis. 0 or 1.
int axis_y_invert; // Whether or not to invert the y axis. 0 or 1.
/* Used by Gestures */
// Set by config.
int trackpad_disable; // Disable the trackpad? 0 or 1
int button_enable; // Enable physical buttons? 0 or 1
int button_integrated; // Is the button under the touchpad? 0 or 1
int button_expire; // How long to consider a touch for button emulation. >= 0
int button_zones; // Use button zones for emulation?
int is_button_zones_height_limited; // Limit the button zones to the height of the bottom edge?
int button_first_zone; // Button to execute when clicking in the leftmost part of the zone (button_#_zones > 0)
int button_second_zone; // Button to execute when clicking right of zone_button1 part of the zone (button_#_zones > 0)
int button_third_zone; // Button to execute when clicking the rightmost part of the zone (button_#_zones > 0)
int button_0touch; // What button to emulate when no finger is on the
// pad and a click is registered? 0 to 32
int button_1touch; // What button to emulate when one finger is on the
// pad or the first zone is clicked? 0 to 32
int button_2touch; // What button to emulate when two fingers are on the
// pad or the second zone is clicked? 0 to 32
int button_3touch; // What button to emulate when three fingers are on the
// pad or the third zone is clicked? 0 to 32
int button_move; // Whether or not to count the moving touch towards button
// emulation.
int tap_1touch; // What button to emulate for one touch taps? 0 to 32
int tap_2touch; // What button to emulate for two touch taps? 0 to 32
int tap_3touch; // What button to emulate for three touch taps? 0 to 32
int tap_4touch; // What button to emulate for four touch taps? 0 to 32
int tap_timeout; // Window for touches when counting for the button.
// How long to wait for incoming touches after first one. > 0
int tap_hold; // How long to "hold down" the emulated button on tap. > 0
int tap_dist; // How far to allow a touch to move before it's a moving touch. > 0
int gesture_hold; // How long to "hold down" the emulated button for gestures. > 0
int gesture_wait; // How long after a gesture to wait before movement is allowed. >= 0
struct MConfigSwipe{
int dist; // Distance needed to trigger a button. >= 0, 0 disables
int hold; // How long to "hold down" the emulated button for swipe gesture. > 0
int drag_sens; // Should this gesture emit movement events? 0 disables movement, 1000 set speed same as during normal movement
int up_btn; // Button to use for swipe up. >= 0, 0 is none
int dn_btn; // Button to use for swipe down. >= 0, 0 is none
int lt_btn; // Button to use for swipe left. >= 0, 0 is none
int rt_btn; // Button to use for swipe right. >= 0, 0 is none
} scroll, swipe3, swipe4/*, swipe5*/;
struct MConfigSwipeCoasting{
float min_speed; // What speed to start scroll coasting at. >= 0
int tick_ms; // How fast events will be generated during coasting >= 1
int duration; // How long coasting ticks will last >= 0, 0 disables coasting
int no_boost; // Disable boosting on second scroll gesture during coasting. 0 or 1
int ease; // Apply easing effect on coasting. 0 or 1
} scroll_coast;
struct MConfigSwipe edge_scroll;
int scale_dist; // Distance needed to trigger a button. >= 0, 0 disables
int scale_up_btn; // Button to use for scale up. >= 0, 0 is none
int scale_dn_btn; // Button to use for scale down. >= 0, 0 is none
int rotate_dist; // Distance needed to trigger a button. >= 0, 0 disables
int rotate_lt_btn; // Button to use for rotate left. >= 0, 0 is none
int rotate_rt_btn; // Button to use for rotate right. >= 0, 0 is none
struct MConfigStationary{
int max_move; // How far stationary finger can move, before interrupting the gesture. >= 0
int button; // Button to be pressed/released when gesture starts/ends. >= 0, 0 disables
} hold1_move1_stationary;
#if 0
struct MConfigStationary hold1_move2_stationary, hold1_move3_stationary;
#endif
struct MConfigSwipe hold1_move1;
#if 0
struct MConfigSwipe hold1_move2, hold1_move3;
#endif
int drag_enable; // Enable tap-to-drag? 0 or 1
int drag_timeout; // How long to wait for a move after tapping? > 0
int drag_wait; // How long to wait before triggering button down? >= 0
int drag_dist; // How far is the finger allowed to move during wait time? >= 0
int drag_lock_timeout; // How long to wait in 'drag ready' state after
// dragging finger was released?
// < 0 - wait of tap to break drag; 0 - disable; > 0 - time in ms
double sensitivity; // Mouse movement multiplier. >= 0
int scroll_smooth; // Enable high precision (smooth) scrolling. 0 or 1.
};
/* Load the MConfig struct with its defaults.
*/
void mconfig_defaults(struct MConfig* cfg);
/* Initialize the MConfig struct.
*/
void mconfig_init(struct MConfig* cfg,
const struct Capabilities* caps);
void mconfig_configure(struct MConfig* cfg,
pointer opts);
#endif
================================================
FILE: include/mprops.h
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifndef MTRACK_PROPS_H
#define MTRACK_PROPS_H
#include <xorg-server.h>
#include <xf86Module.h>
#include <X11/Xatom.h>
#include <xf86.h>
#include <xf86Xinput.h>
#include <exevents.h>
#include "mconfig.h"
#ifndef XATOM_FLOAT
#define XATOM_FLOAT "FLOAT"
#endif
// int, 1 value
#define MTRACK_PROP_TRACKPAD_DISABLE "Trackpad Disable Input"
// float, 1 value
#define MTRACK_PROP_SENSITIVITY "Trackpad Sensitivity"
// int, 2 values - finger low, finger high
#define MTRACK_PROP_PRESSURE "Trackpad Touch Pressure"
// int, 2 values - enable buttons, has integrated button
#define MTRACK_PROP_BUTTON_SETTINGS "Trackpad Button Settings"
// int, 4 values - enable button zones, button move emulation, emulation touch expiration, button zone in edge bottom
#define MTRACK_PROP_BUTTON_EMULATE_SETTINGS "Trackpad Button Emulation Settings"
// int, 7 values - button to emulate with 0 touch, 1 touch, 2 touches, 3 touches AND zone 1, zone 2, zone 3
#define MTRACK_PROP_BUTTON_EMULATE_VALUES "Trackpad Button Emulation Values"
// int, 3 values - click time, touch timeout, invalidate distance
#define MTRACK_PROP_TAP_SETTINGS "Trackpad Tap Settings"
// int, 4 values - 1 touch button, 2 touch button, 3 touch button, 4 touch button
#define MTRACK_PROP_TAP_EMULATE "Trackpad Tap Button Emulation"
// int, 2 values - ignore thumb touches, disable trackpad on thumb touches
#define MTRACK_PROP_THUMB_DETECT "Trackpad Thumb Detection"
// int, 2 values - size, width to length ratio
#define MTRACK_PROP_THUMB_SIZE "Trackpad Thumb Size"
// int, 2 values - ignore palm touches, disable trackpad on palm touches
#define MTRACK_PROP_PALM_DETECT "Trackpad Palm Detection"
// int, 1 value - size
#define MTRACK_PROP_PALM_SIZE "Trackpad Palm Size"
// int, 2 value - button hold, wait time
#define MTRACK_PROP_GESTURE_SETTINGS "Trackpad Gesture Settings"
// int, 1 value - enable high precision scrolling
#define MTRACK_PROP_SMOOTH_SCROLL "Trackpad Smooth Scroll"
// int, 3 values
// first: distance before a scroll event (two finger swipe) is triggered
// second: how much milliseconds button will be hold after {up,down,left,right} scroll
// third: sensitivity of the pointer during scroll gesture multiplied by 1000, value of 0 disables drag-to-move
#define MTRACK_PROP_SCROLL_SETTINGS "Trackpad Scroll Settings"
// int, 4 values - up button, down button, left button, right button
#define MTRACK_PROP_SCROLL_BUTTONS "Trackpad Scroll Buttons"
// int, 3 values - enable coasting, coasting enable speed, decelaration amount
#define MTRACK_PROP_SCROLL_COAST "Trackpad Scroll Coasting"
// int, 2 values
// first: distance before a three finger swipe event is triggered
// second: how much milliseconds button will be hold after {up,down,left,right} swipe
// third: sensitivity of the pointer during three finger swipe gesture multiplied by 1000, value of 0 disables drag-to-move
#define MTRACK_PROP_SWIPE_SETTINGS "Trackpad Swipe Settings"
// int, 4 values - up button, down button, left button, right button
#define MTRACK_PROP_SWIPE_BUTTONS "Trackpad Swipe Buttons"
// int, 3 values
// first: distance before a four finger swipe event is triggered
// second: how much milliseconds button will be hold after {up,down,left,right} swipe4
// third: sensitivity of the pointer during four finger swipe gesture multiplied by 1000, value of 0 disables drag-to-move
#define MTRACK_PROP_SWIPE4_SETTINGS "Trackpad Swipe4 Settings"
// int, 4 values - up button, down button, left button, right button
#define MTRACK_PROP_SWIPE4_BUTTONS "Trackpad Swipe4 Buttons"
// int, 7 values
// first: distance before event triggered (0 disable)
// second: how much miliseconds to hold button down
// third: sensitivity of the pointer during gesture
// rest: {up,down,left,right} buttons
#define MTRACK_PROP_EDGE_SCROLL_SETTINGS "Trackpad Edge Scroll Settings"
// int, 4 value - size of edge regions that are ignored: {up,down,left,right}
#define MTRACK_PROP_EDGE_SIZES "Trackpad Edge Sizes"
// int, 1 value - distance before a scale event is triggered
#define MTRACK_PROP_SCALE_DIST "Trackpad Scale Distance"
// int, 2 values - up button, down button
#define MTRACK_PROP_SCALE_BUTTONS "Trackpad Scale Buttons"
// int, 1 value - distance before a rotate event is triggered
#define MTRACK_PROP_ROTATE_DIST "Trackpad Rotate Distance"
// int, 2 values - left button, right button
#define MTRACK_PROP_ROTATE_BUTTONS "Trackpad Rotate Buttons"
// int, 2 values - hold&move with one stationary and one moving finger
// first: stationary finger max move distance
// second: button
#define MTRACK_PROP_HOLD1_MOVE1_STATIONARY_SETTINGS "Trackpad Hold1Move1 Stationary Settings"
// int, 2 values
// first: distance before a four swipe event is triggered
// second: how much milliseconds button will be hold after gesture
#define MTRACK_PROP_HOLD1_MOVE1_SETTINGS "Trackpad Hold1Move1 Settings"
// int, 4 values - up button, down button, left button, right button
#define MTRACK_PROP_HOLD1_MOVE1_BUTTONS "Trackpad Hold1Move1 Buttons"
// int, 2 values - hold&move with one stationary and two moving fingers
// first: stationary finger max move distance
// second: button
#define MTRACK_PROP_HOLD1_MOVE2_STATIONARY_SETTINGS "Trackpad Hold1Move2 Stationary Settings"
// int, 2 values
// first: distance before a four swipe event is triggered
// second: how much milliseconds button will be hold after gesture
#define MTRACK_PROP_HOLD1_MOVE2_SETTINGS "Trackpad Hold1Move2 Settings"
// int, 4 values - up button, down button, left button, right button
#define MTRACK_PROP_HOLD1_MOVE2_BUTTONS "Trackpad Hold1Move2 Buttons"
// int, 2 values - hold&move with one stationary and three moving finger
// first: stationary finger max move distance
// second: button
#define MTRACK_PROP_HOLD1_MOVE3_STATIONARY_SETTINGS "Trackpad Hold1Move3 Stationary Settings"
// int, 2 values
// first: distance before a four swipe event is triggered
// second: how much milliseconds button will be hold after gesture
#define MTRACK_PROP_HOLD1_MOVE3_SETTINGS "Trackpad Hold1Move3 Settings"
// int, 4 values - up button, down button, left button, right button
#define MTRACK_PROP_HOLD1_MOVE3_BUTTONS "Trackpad Hold1Move3 Buttons"
// int, 5 values - enable, timeout, wait, dist, lock timeout
#define MTRACK_PROP_DRAG_SETTINGS "Trackpad Drag Settings"
// int, 2 values - invert x axis, invert y axis
#define MTRACK_PROP_AXIS_INVERT "Trackpad Axis Inversion"
struct MProps {
// Properties Config
Atom float_type;
// Adjustable Properties
Atom api;
Atom trackpad_disable;
Atom sensitivity;
Atom pressure;
Atom button_settings;
Atom button_emulate_settings;
Atom button_emulate_values;
Atom tap_settings;
Atom tap_emulate;
Atom thumb_detect;
Atom thumb_size;
Atom palm_detect;
Atom palm_size;
Atom gesture_settings;
Atom scroll_smooth;
struct MPropsSwipe{
Atom settings;
Atom buttons;
} scroll, swipe3, swipe4/*, swipe5*/;
Atom scroll_coast;
Atom edge_scroll;
Atom scale_dist;
Atom scale_buttons;
Atom rotate_dist;
Atom rotate_buttons;
Atom hold1_move1_stationary;
struct MPropsSwipe hold1_move1;
#if 0
Atom hold1_move2_stationary;
struct MPropsSwipe hold1_move2;
Atom hold1_move3_stationary;
struct MPropsSwipe hold1_move3;
#endif
Atom drag_settings;
Atom axis_invert;
Atom edge_sizes;
};
void mprops_init(struct MConfig* cfg, InputInfoPtr local);
int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, BOOL checkonly);
#endif
================================================
FILE: include/mtouch.h
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
* Copyright (C) 2015-2018 Paweł Turkowski <p2rkw0@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifndef MTOUCH_H
#define MTOUCH_H
#include "common.h"
#include "capabilities.h"
#include "hwstate.h"
#include "mtstate.h"
#include "mconfig.h"
#include "gestures.h"
#include "os.h" /* xorg/os.h for timers */
struct MTouch {
int fd;
struct mtdev dev;
struct Capabilities caps;
struct HWState hs;
struct MTState state;
struct MConfig cfg;
struct Gestures gs;
int timer_kind; // to avoid setting timer multiple times
/*
* Timers documentation:
* http://www.x.org/releases/X11R7.7/doc/xorg-server/Xserver-spec.html#id2536042
*/
OsTimerPtr timer;
int absolute_mode; // Should absolute mode be enabled ? 0 or 1
ValuatorMask* valuator_mask;
DeviceIntPtr local_dev;
};
int mtouch_configure(struct MTouch* mt, int fd);
int mtouch_open(struct MTouch* mt, int fd);
int mtouch_close(struct MTouch* mt);
int mtouch_read(struct MTouch* mt);
int mtouch_delayed(struct MTouch* mt);
/**
* \defgroup Timers Perform asynchronous tasks
*
* Timers are defined by labels (IDs). To add new timer create new ID, and implement
* appropriate section in mt_timer_start, mt_timer_stop, and mt_timer_callback.
*
* All timers share same X resource, so generally you can't have more than one timer
* ticking at time. For now it's fine.
*
* Functions are implemented in mtrack.c
*
* @{
*/
/** Will cancel any timer */
#define MT_TIMER_ANY -1
#define MT_TIMER_NONE 0
/* #define -MT_TIMER_ANY 1 - reserved */
#define MT_TIMER_DELAYED_BUTTON 2
#define MT_TIMER_COASTING 3
void mt_timer_start(struct MTouch *mt, int kind);
/**
* Executed on early stop.
* For example when one timer is replaced by naother.
* @param mt
*/
void mt_timer_stop(struct MTouch *mt);
CARD32 mt_timer_callback(OsTimerPtr timer, CARD32 time, void *arg);
void mt_timer_stop_if(struct MTouch *mt, int kind);
/**
* Restart timer with same kind.
* Does not call start nor stop callbacks.
* @param mt
*/
void mt_timer_continue(struct MTouch *mt, mstime_t timeout);
/**
* Kind > 0 starts timer, kind < 0 stops timer with ID == abs(kind).
* MT_TIMER_ANY stops whatever timer is running.
* @param mt
* @param kind
*/
void mt_timer_start_or_stop(struct MTouch *mt, int kind);
/** }@ */
#endif
================================================
FILE: include/mtstate.h
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifndef MTSTATE_H
#define MTSTATE_H
#include "common.h"
#include "mconfig.h"
#include "hwstate.h"
#include "capabilities.h"
#define MT_NEW 0
#define MT_RELEASED 1
#define MT_INVALID 2
#define MT_THUMB 3
#define MT_PALM 4
#define MT_EDGE 5
#define MT_TAP 6
#define MT_BUTTON 7
struct Touch {
bitmask_t flags;
double direction;
int tracking_id;
int x, y, dx, dy;
int total_dx, total_dy;
struct timeval down;
};
struct MTState {
bitmask_t touch_used;
struct Touch touch[DIM_TOUCHES];
};
/*
* |1| 2 |3|
* |-|-------|-|
* |4| 5 |6|
* |-|-------|-|
* |7| 8 |9|
*/
int touch_which_edge(const struct MConfig* cfg, const struct Touch* t);
/* Initialize an MTState struct.
*/
void mtstate_init(struct MTState* ms);
/* Extract the MTState from the current hardware state.
*/
void mtstate_extract(struct MTState* ms,
const struct MConfig* cfg,
const struct HWState* hs,
const struct Capabilities* caps);
#endif
================================================
FILE: include/trig.h
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
/* Some bastardized trig functions. These calculations flip the
* Y axis since that axis on touchpads is opposite that of the
* Cartesian system.
*/
#ifndef MT_TRIG_H
#define MT_TRIG_H
#define TR_NONE -1
#define TR_DIR_UP 0
#define TR_DIR_RT 2
#define TR_DIR_DN 4
#define TR_DIR_LT 6
/* Determine the direction of a vector. This uses the slope of the
* vector to approximate the angle, as such it is only accurate at
* increments of 45 degrees. This is sufficient for our uses.
*
* The returned value is 0 <= a < 8 such that the circle is split
* into 45 degree sections. Each whole number lies 45 degrees apart
* and so whole numbers are exact. All fractional parts are
* aproximations.
*
* TR_NONE will be returned if the magnitude of the vector is zero.
*/
double trig_direction(double dx, double dy);
/* Generalize a direction. Returns TR_NONE, TR_DIR_UP, TR_DIR_RT,
* TR_DIR_DN, or TR_DIR_LT.
*/
int trig_generalize(double dir);
/* Add two angles.
*/
double trig_angles_add(double a1, double a2);
/* Subtract two angles.
*/
double trig_angles_sub(double a1, double a2);
/* Calculate the acute angle between two angles.
*/
double trig_angles_acute(double a1, double a2);
/* Average a collection of angles.
*/
double trig_angles_avg(double* angles, int len);
/* Compare two angles. Returns 0 if a1 == a2. Returns < 0 if a1 < a2.
* Returns > 0 if a1 > a2.
*/
int trig_angles_cmp(double a1, double a2);
#endif
================================================
FILE: required_packages.txt
================================================
xserver-xorg-dev mtdev-dev libmtdev-dev xutils-dev
================================================
FILE: src/capabilities.c
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#include "capabilities.h"
#define SETABS(c, x, map, key, fd) \
(c->has_##x = getbit(map, key) && getabs(&c->x, key, fd))
#define ADDCAP(s, c, x) strcat(s, c->has_##x ? " " #x : "")
static const int SN_COORD = 250; /* coordinate signal-to-noise ratio */
static const int SN_WIDTH = 100; /* width signal-to-noise ratio */
static const int SN_ORIENT = 10; /* orientation signal-to-noise ratio */
static const int bits_per_long = 8 * sizeof(long);
static inline int nlongs(int nbit)
{
return (nbit + bits_per_long - 1) / bits_per_long;
}
static inline int getbit(const unsigned long *map, int key)
{
return (map[key / bits_per_long] >> (key % bits_per_long)) & 0x01;
}
static int getabs(struct input_absinfo *abs, int key, int fd)
{
int rc;
SYSCALL(rc = ioctl(fd, EVIOCGABS(key), abs));
return rc >= 0;
}
static int has_mt_data(const struct Capabilities *cap)
{
return cap->has_abs[MTDEV_POSITION_X] && cap->has_abs[MTDEV_POSITION_Y];
}
static int has_integrated_button(const struct Capabilities *cap)
{
static const int bcm5974_vmask_ibt = 1;
/* magic trackpad */
if (cap->devid.vendor == 0x05ac && cap->devid.product == 0x030e)
return 1;
/* macbooks */
if (strcmp(cap->devname, "bcm5974"))
return 0;
return cap->devid.version & bcm5974_vmask_ibt;
}
static void default_fuzz(struct Capabilities *cap, unsigned int code, int sn)
{
int bit = mtdev_abs2mt(code);
if (cap->has_abs[bit] && cap->abs[bit].fuzz == 0)
cap->abs[bit].fuzz =
(cap->abs[bit].maximum - cap->abs[bit].minimum) / sn;
}
int read_capabilities(struct Capabilities *cap, int fd)
{
unsigned long evbits[nlongs(EV_MAX)];
unsigned long absbits[nlongs(ABS_MAX)];
unsigned long keybits[nlongs(KEY_MAX)];
int rc, i;
memset(cap, 0, sizeof(struct Capabilities));
SYSCALL(rc = ioctl(fd, EVIOCGID, &cap->devid));
if (rc < 0)
return rc;
SYSCALL(rc = ioctl(fd, EVIOCGNAME(sizeof(cap->devname) - 1), cap->devname));
if (rc < 0)
return rc;
SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_SYN, sizeof(evbits)), evbits));
if (rc < 0)
return rc;
SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits));
if (rc < 0)
return rc;
SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits));
if (rc < 0)
return rc;
cap->has_left = getbit(keybits, BTN_LEFT);
cap->has_middle = getbit(keybits, BTN_MIDDLE);
cap->has_right = getbit(keybits, BTN_RIGHT);
SETABS(cap, slot, absbits, ABS_MT_SLOT, fd);
for (i = 0; i < MT_ABS_SIZE; i++)
SETABS(cap, abs[i], absbits, mtdev_mt2abs(i), fd);
cap->has_mtdata = has_mt_data(cap);
cap->has_ibt = has_integrated_button(cap);
default_fuzz(cap, ABS_MT_POSITION_X, SN_COORD);
default_fuzz(cap, ABS_MT_POSITION_Y, SN_COORD);
default_fuzz(cap, ABS_MT_TOUCH_MAJOR, SN_WIDTH);
default_fuzz(cap, ABS_MT_TOUCH_MINOR, SN_WIDTH);
default_fuzz(cap, ABS_MT_WIDTH_MAJOR, SN_WIDTH);
default_fuzz(cap, ABS_MT_WIDTH_MINOR, SN_WIDTH);
default_fuzz(cap, ABS_MT_ORIENTATION, SN_ORIENT);
//#define MIMIC_CUSTOM_CAPS
#ifdef MIMIC_CUSTOM_CAPS
cap->has_abs[MTDEV_POSITION_X] = 1;
cap->has_abs[MTDEV_POSITION_Y] = 1;
cap->has_abs[MTDEV_TRACKING_ID] = 1;
cap->has_abs[MTDEV_TOUCH_MAJOR] = 0;
cap->has_abs[MTDEV_TOUCH_MINOR] = 0;
cap->has_abs[MTDEV_WIDTH_MAJOR] = 0;
cap->has_abs[MTDEV_WIDTH_MINOR] = 0;
cap->has_abs[MTDEV_ORIENTATION] = 0;
cap->has_abs[MTDEV_PRESSURE] = 0;
#endif
return 0;
}
int get_cap_xsize(const struct Capabilities *cap)
{
const struct input_absinfo *x = &cap->abs[MTDEV_POSITION_X];
return x->maximum - x->minimum;
}
int get_cap_ysize(const struct Capabilities *cap)
{
const struct input_absinfo *y = &cap->abs[MTDEV_POSITION_Y];
return y->maximum - y->minimum;
}
int get_cap_wsize(const struct Capabilities *cap)
{
const struct input_absinfo *w = &cap->abs[MTDEV_TOUCH_MAJOR];
return w->maximum - w->minimum;
}
int get_cap_xmid(const struct Capabilities *cap)
{
const struct input_absinfo *x = &cap->abs[MTDEV_POSITION_X];
return (x->maximum + x->minimum) >> 1;
}
int get_cap_ymid(const struct Capabilities *cap)
{
const struct input_absinfo *y = &cap->abs[MTDEV_POSITION_Y];
return (y->maximum + y->minimum) >> 1;
}
int translate_cap_x(const struct Capabilities *cap, int x)
{
int mid = get_cap_xmid(cap);
return x - mid;
}
int translate_cap_y(const struct Capabilities *cap, int y)
{
int mid = get_cap_ymid(cap);
return y - mid;
}
int get_cap_xmin(const struct Capabilities *cap)
{
const struct input_absinfo *x = &cap->abs[MTDEV_POSITION_X];
return x->minimum;
}
int get_cap_ymin(const struct Capabilities *cap)
{
const struct input_absinfo *y = &cap->abs[MTDEV_POSITION_Y];
return y->minimum;
}
void output_capabilities(const struct Capabilities *cap)
{
char line[1024];
int i;
LOG_INFO("Capabilities: \n");
LOG_INFO_CONT("devname: %s\n", cap->devname);
LOG_INFO_CONT("devid: %x %x %x\n", cap->devid.vendor, cap->devid.product, cap->devid.version);
char cap_names[MT_ABS_SIZE][24] = {
"ABS_MT_TOUCH_MAJOR", "ABS_MT_TOUCH_MINOR",
"ABS_MT_WIDTH_MAJOR", "ABS_MT_WIDTH_MINOR",
"ABS_MT_ORIENTATION",
"ABS_MT_POSITION_X", "ABS_MT_POSITION_Y",
"ABS_MT_TOOL_TYPE",
"ABS_MT_BLOB_ID",
"ABS_MT_TRACKING_ID",
"ABS_MT_PRESSURE"
};
for (i = 0; i < MT_ABS_SIZE; i++) {
if (cap->has_abs[i])
LOG_INFO_CONT("%s: min: %d max: %d\n",
cap_names[i],
cap->abs[i].minimum,
cap->abs[i].maximum);
}
if(cap->has_slot)
LOG_INFO_CONT("ABS_MT_SLOT: min: %d max: %d\n", cap->slot.minimum, cap->slot.maximum);
memset(line, 0, sizeof(line));
ADDCAP(line, cap, left);
ADDCAP(line, cap, middle);
ADDCAP(line, cap, right);
ADDCAP(line, cap, mtdata);
ADDCAP(line, cap, ibt);
ADDCAP(line, cap, slot);
LOG_INFO_CONT("enabled caps:%s\n", line);
}
================================================
FILE: src/gestures.c
================================================
/***************************************************************************
*
* Multitouch X driver
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
* Copyright (C) 2015-2018 Paweł Turkowski <p2rkw0@gmail.com>
*
* Gestures
* Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
* Copyright (C) 2010 Arturo Castro <mail@arturocastro.net>
* Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
* Copyright (C) 2015-2018 Paweł Turkowski <p2rkw0@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#include "gestures.h"
#include "mtouch.h"
#include "trig.h"
//#define DEBUG_GESTURES 1
#ifdef DEBUG_GESTURES
# define LOG_DEBUG_GESTURES LOG_DEBUG
# define LOG_EMULATED LOG_INFO
#else
# define LOG_DEBUG_GESTURES LOG_DISABLED
# define LOG_EMULATED LOG_DISABLED
#endif
#define IS_VALID_BUTTON(x) (x >= 0 && x <= 31)
static void break_coasting(struct Gestures* gs){
gs->scroll_speed_x = gs->scroll_speed_y = 0.0f;
}
static void trigger_button_up(struct Gestures* gs, int button)
{
if (IS_VALID_BUTTON(button)) {
if (button == 0 && gs->button_emulate > 0) {
button = gs->button_emulate;
gs->button_emulate = 0;
}
CLEARBIT(gs->buttons, button);
LOG_DEBUG_GESTURES("trigger_button_up: %d up\n", button);
}
}
static void trigger_button_down(struct Gestures* gs, int button)
{
struct timeval epoch;
timerclear(&epoch);
if (IS_VALID_BUTTON(button) &&
(button != gs->button_delayed || !IS_VALID_BUTTON(gs->button_delayed))
) {
SETBIT(gs->buttons, button);
LOG_DEBUG_GESTURES("trigger_button_down: %d down\n", button);
}
else if (IS_VALID_BUTTON(button))
LOG_DEBUG_GESTURES("trigger_button_down: %d down ignored, in delayed mode\n", button);
}
static void trigger_button_emulation(struct Gestures* gs, int button)
{
#if 0
if (IS_VALID_BUTTON(button) && GETBIT(gs->buttons, 0)) {
CLEARBIT(gs->buttons, 0);
SETBIT(gs->buttons, button);
gs->button_emulate = button;
LOG_DEBUG_GESTURES("trigger_button_emulation: %d emulated\n", button);
}
#else
trigger_button_down(gs, button);
gs->integrated_emulated_button = button + 1;
#endif
}
static void trigger_button_emulation_end(struct Gestures* gs)
{
if(gs->integrated_emulated_button > 0){
trigger_button_up(gs, gs->integrated_emulated_button - 1);
gs->integrated_emulated_button = 0;
}
}
int trigger_delayed_button_uncond(struct Gestures* gs)
{
int button;
// clear button before timer (unless compiler decide otherwise)
button = gs->button_delayed;
gs->button_delayed = -1;
timerclear(&gs->button_delayed_time);
gs->move_dist = 0; /* don't count movement from delayed button phase in next stroke */
LOG_DEBUG_GESTURES("trigger_delayed_button: %d up, timer expired\n", button);
trigger_button_up(gs, button);
return button;
}
/*
* If trigger_up_time is NULL or epoch time it will set timer to infinity - button up will
* be send when user finish gesture.
*/
static void trigger_button_click(struct Gestures* gs,
int button, struct timeval* trigger_up_time)
{
#ifdef DEBUG_GESTURES
struct timeval delta;
#endif
if (!IS_VALID_BUTTON(button))
return;
if (!IS_VALID_BUTTON(gs->button_delayed)) {
trigger_button_down(gs, button);
gs->button_delayed = button;
if(trigger_up_time == NULL)
timerclear(&gs->button_delayed_time); // "infinite timer", wait for gesture end
else
timercp(&gs->button_delayed_time, trigger_up_time); // may be also "infinite"
#ifdef DEBUG_GESTURES
timersub(&gs->button_delayed_time, &gs->time, &delta);
LOG_DEBUG_GESTURES("trigger_button_click: %d placed in delayed mode; delta: %lld ms\n", button, timertoms(&delta));
#endif
}
#ifdef DEBUG_GESTURES
else
LOG_DEBUG_GESTURES("trigger_button_click: %d ignored, in delayed mode\n", button);
#endif
}
static void reset_drag(struct Gestures* gs){
if (gs->drag_state == GS_DRAG_ACTIVE) {
gs->drag_state = GS_NONE;
timerclear(&gs->move_drag_expire);
trigger_button_up(gs, 0);
LOG_DEBUG_GESTURES("reset_drag: drag stopped\n");
}
}
static void trigger_drag_ready(struct Gestures* gs,
const struct MConfig* cfg)
{
gs->drag_state = GS_DRAG_READY;
timeraddms(&gs->time, cfg->drag_timeout, &gs->move_drag_expire);
LOG_DEBUG_GESTURES("trigger_drag_ready: drag is ready\n");
/* Break coasting */
break_coasting(gs);
}
static int trigger_drag_start(struct Gestures* gs,
const struct MConfig* cfg,
int dx, int dy)
{
if (gs->drag_state == GS_DRAG_READY) {
timerclear(&gs->move_drag_expire);
if (cfg->drag_wait == 0) {
gs->drag_state = GS_DRAG_ACTIVE;
trigger_button_down(gs, 0);
LOG_DEBUG_GESTURES("trigger_drag_start: drag is active\n");
}
else {
gs->drag_state = GS_DRAG_WAIT;
gs->move_drag_dx = dx;
gs->move_drag_dy = dy;
timeraddms(&gs->time, cfg->drag_wait, &gs->move_drag_wait);
LOG_DEBUG_GESTURES("trigger_drag_start: drag in wait\n");
}
}
else if (gs->drag_state == GS_DRAG_WAIT) {
gs->move_drag_dx += dx;
gs->move_drag_dy += dy;
if (!timercmp(&gs->time, &gs->move_drag_wait, <)) {
gs->drag_state = GS_DRAG_ACTIVE;
trigger_button_down(gs, 0);
LOG_DEBUG_GESTURES("trigger_drag_start: drag is active\n");
}
else if (dist2(gs->move_drag_dx, gs->move_drag_dy) > SQRVAL(cfg->drag_dist)) {
gs->drag_state = GS_NONE;
LOG_DEBUG_GESTURES("trigger_drag_start: drag canceled, moved too far\n");
}
}
return gs->drag_state != GS_DRAG_WAIT;
}
static void trigger_drag_stop(struct Gestures* gs, const struct MConfig* cfg)
{
int lock_timeout;
lock_timeout = cfg->drag_lock_timeout;
if (gs->drag_state == GS_DRAG_READY) {
/* if timeout < 0 then tap-dragging will require another tap to break the drag */
if (lock_timeout >= 0 && timercmp(&gs->time, &gs->move_drag_expire, >=)) {
LOG_DEBUG_GESTURES("trigger_drag_stop: locked drag expored\n");
trigger_button_up(gs, 0);
}
gs->drag_state = GS_NONE;
timerclear(&gs->move_drag_expire);
LOG_DEBUG_GESTURES("trigger_drag_stop: drag canceled\n");
}
else if (gs->drag_state == GS_DRAG_ACTIVE) {
if(lock_timeout == 0){
reset_drag(gs);
}
else{
/* Tap to drag lock timeout implementaion:
* Instead of breaking dragging completely, just take one step back
* to ready state and start timer waiting for future dragging */
gs->drag_state = GS_DRAG_READY;
timeraddms(&gs->time, lock_timeout, &gs->move_drag_expire);
LOG_DEBUG_GESTURES("trigger_drag_stop: drag in wait lock\n");
}
}
}
/* Return 0 if current time stamp is greater than move_wait time stamp. */
static int can_change_gesture_type(struct Gestures* gs, int desired_gesture){
if (gs->move_type == desired_gesture)
return 1;
if(gs->move_type == GS_NONE || gs->move_type == GS_MOVE)
return 1;
return timercmp(&gs->time, &gs->move_wait, >);
}
static void buttons_update(struct Gestures* gs,
const struct MConfig* cfg,
const struct HWState* hs,
struct MTState* ms)
{
if (!cfg->button_enable || cfg->trackpad_disable >= 3)
return;
static bitmask_t button_prev = 0U;
int i, integrated_down, integrated_up;
int integrated_just_clicked, integrated_just_released;
integrated_down = 0;
integrated_up = 0;
integrated_just_clicked = GETBIT(hs->button, 0) && !GETBIT(button_prev, 0);
integrated_just_released = !GETBIT(hs->button, 0) && GETBIT(button_prev, 0);
for (i = 0; i < 32; i++) {
if (GETBIT(hs->button, i) == GETBIT(button_prev, i))
continue;
if (GETBIT(hs->butto
gitextract_jeyfc4m8/
├── .gitignore
├── COPYING
├── CREDITS
├── Makefile.am
├── README.md
├── RELEASE.md
├── configure.ac
├── debian/
│ ├── README.Debian
│ ├── changelog
│ ├── compat
│ ├── control
│ ├── copyright
│ ├── dirs
│ └── rules
├── driver/
│ ├── mprops.c
│ └── mtrack.c
├── examples/
│ ├── acer-aspire-s3.conf
│ ├── asus-zenbook-ux330ua-ah55
│ ├── dell-precision-5520.conf
│ ├── dell-xps13-9333.conf
│ ├── lenovo-710s.conf
│ ├── lenovo-yoga-2-pro.conf
│ ├── macbook-pro-retina-2013.conf
│ └── macbook.conf
├── include/
│ ├── button.h
│ ├── capabilities.h
│ ├── common.h
│ ├── gestures.h
│ ├── hwstate.h
│ ├── mconfig.h
│ ├── mprops.h
│ ├── mtouch.h
│ ├── mtstate.h
│ └── trig.h
├── required_packages.txt
├── src/
│ ├── capabilities.c
│ ├── gestures.c
│ ├── hwstate.c
│ ├── mconfig.c
│ ├── mtouch.c
│ ├── mtstate.c
│ └── trig.c
└── tools/
├── mtrack-test.c
└── reconfigure-xinput.sh
SYMBOL INDEX (221 symbols across 18 files)
FILE: driver/mprops.c
type MProps (line 40) | struct MProps
function Atom (line 42) | Atom atom_init_integer(DeviceIntPtr dev, char* name, int nvalues, int* v...
function Atom (line 78) | static
function Atom (line 90) | Atom atom_init_float(DeviceIntPtr dev, char* name, int nvalues, float* v...
function init_swipe_props (line 97) | static void init_swipe_props(DeviceIntPtr dev, struct MPropsSwipe* props...
function init_edge_props (line 113) | static void init_edge_props(DeviceIntPtr dev, Atom* props_edge,
function mprops_init (line 129) | void mprops_init(struct MConfig* cfg, InputInfoPtr local) {
function check_buttons_property (line 269) | int check_buttons_property(XIPropertyValuePtr prop, uint8_t** buttons_re...
function set_swipe_properties (line 291) | static int set_swipe_properties(DeviceIntPtr dev, Atom property, XIPrope...
function mprops_set_property (line 335) | int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValue...
FILE: driver/mtrack.c
type InputInfoPtr (line 56) | typedef InputInfoPtr LocalDevicePtr;
function pointer_control (line 62) | static void pointer_control(DeviceIntPtr dev, PtrCtrl *ctrl)
function init_axes_labels (line 68) | static void init_axes_labels(Atom map[NUM_AXES])
function init_button_labels (line 77) | static void init_button_labels(Atom map[DIM_BUTTON])
function init_axle_absolute (line 112) | static void init_axle_absolute(DeviceIntPtr dev, int axnum, Atom* label)
function init_axle_relative (line 130) | static void init_axle_relative(DeviceIntPtr dev, int axnum, Atom* label)
function device_init (line 136) | static int device_init(DeviceIntPtr dev, LocalDevicePtr local)
function device_on (line 204) | static int device_on(LocalDevicePtr local)
function device_off (line 228) | static int device_off(LocalDevicePtr local)
function device_close (line 242) | static int device_close(LocalDevicePtr local)
type MTouch (line 247) | struct MTouch
function mt_timer_start (line 249) | void mt_timer_start(struct MTouch *mt, int kind)
function mt_timer_stop (line 292) | void mt_timer_stop(struct MTouch *mt)
function CARD32 (line 325) | CARD32 mt_timer_callback(OsTimerPtr timer, CARD32 time, void *arg)
function mt_timer_start_or_stop (line 384) | void mt_timer_start_or_stop(struct MTouch *mt, int kind)
function mt_timer_stop_if (line 392) | void mt_timer_stop_if(struct MTouch *mt, int kind)
function mt_timer_continue (line 398) | void mt_timer_continue(struct MTouch *mt, mstime_t timeout)
function can_start_coasting (line 408) | static int can_start_coasting(struct MTouch *mt)
function post_gestures (line 432) | static void post_gestures(struct MTouch *mt)
function post_button (line 500) | static void post_button(struct MTouch* mt, int button, int new_state)
function read_input (line 534) | static void read_input(LocalDevicePtr local)
function switch_mode (line 547) | static int switch_mode(ClientPtr client, DeviceIntPtr dev, int mode)
function Bool (line 568) | static Bool device_control(DeviceIntPtr dev, int mode)
function preinit (line 592) | static int preinit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
function InputInfoPtr (line 615) | static InputInfoPtr preinit(InputDriverPtr drv, IDevPtr dev, int flags)
function uninit (line 646) | static void uninit(InputDriverPtr drv, InputInfoPtr local, int flags)
function pointer (line 683) | static pointer setup(pointer module, pointer options, int *errmaj, int *...
FILE: include/capabilities.h
type Capabilities (line 28) | struct Capabilities {
type Capabilities (line 39) | struct Capabilities
type Capabilities (line 40) | struct Capabilities
type Capabilities (line 41) | struct Capabilities
type Capabilities (line 42) | struct Capabilities
type Capabilities (line 44) | struct Capabilities
type Capabilities (line 45) | struct Capabilities
type Capabilities (line 47) | struct Capabilities
type Capabilities (line 48) | struct Capabilities
type Capabilities (line 50) | struct Capabilities
type Capabilities (line 51) | struct Capabilities
type Capabilities (line 53) | struct Capabilities
FILE: include/common.h
type __u64 (line 43) | typedef __u64 mstime_t;
type bitmask_t (line 46) | typedef unsigned int bitmask_t;
function get_next_log_number (line 102) | static inline int get_next_log_number(){
function microtime (line 109) | static inline void microtime(struct timeval* tv)
function timercp (line 116) | static inline void timercp(struct timeval* dest, const struct timeval* src)
function mstime_t (line 124) | static inline mstime_t timertoms(const struct timeval* tv)
function timerfromms (line 131) | static inline void timerfromms(struct timeval* tv, const mstime_t ms)
function suseconds_t (line 139) | static inline suseconds_t timertomicro(const struct timeval* tv)
function timeraddms (line 146) | static inline void timeraddms(const struct timeval* a, const mstime_t b,...
function isepochtime (line 155) | static inline int isepochtime(const struct timeval* a)
function clamp15 (line 165) | static inline int clamp15(int x)
function dist2 (line 172) | static inline int dist2(int dx, int dy)
function bitcount (line 183) | static inline int bitcount(unsigned v)
type Gestures (line 211) | struct Gestures
type Gestures (line 231) | struct Gestures
FILE: include/gestures.h
type MTouch (line 32) | struct MTouch
type Gestures (line 49) | struct Gestures {
type MTouch (line 106) | struct MTouch
type MTouch (line 107) | struct MTouch
type MTouch (line 108) | struct MTouch
type Gestures (line 111) | struct Gestures
type MConfig (line 112) | struct MConfig
type MTState (line 113) | struct MTState
type Gestures (line 116) | struct Gestures
type MConfig (line 117) | struct MConfig
type MTState (line 118) | struct MTState
FILE: include/hwstate.h
type FingerState (line 28) | struct FingerState {
type HWState (line 38) | struct HWState {
type HWState (line 47) | struct HWState
type Capabilities (line 48) | struct Capabilities
type HWState (line 49) | struct HWState
type mtdev (line 50) | struct mtdev
type Capabilities (line 51) | struct Capabilities
type HWState (line 52) | struct HWState
type HWState (line 54) | struct HWState
FILE: include/mconfig.h
type MConfig (line 128) | struct MConfig {
type MConfig (line 238) | struct MConfig
type MConfig (line 242) | struct MConfig
type Capabilities (line 243) | struct Capabilities
type MConfig (line 245) | struct MConfig
FILE: include/mprops.h
type MProps (line 144) | struct MProps {
type MConfig (line 187) | struct MConfig
FILE: include/mtouch.h
type MTouch (line 35) | struct MTouch {
type MTouch (line 54) | struct MTouch
type MTouch (line 55) | struct MTouch
type MTouch (line 56) | struct MTouch
type MTouch (line 58) | struct MTouch
type MTouch (line 59) | struct MTouch
type MTouch (line 83) | struct MTouch
type MTouch (line 89) | struct MTouch
type MTouch (line 91) | struct MTouch
type MTouch (line 97) | struct MTouch
type MTouch (line 104) | struct MTouch
FILE: include/mtstate.h
type Touch (line 40) | struct Touch {
type MTState (line 49) | struct MTState {
type MConfig (line 61) | struct MConfig
type Touch (line 61) | struct Touch
type MTState (line 65) | struct MTState
type MTState (line 69) | struct MTState
type MConfig (line 70) | struct MConfig
type HWState (line 71) | struct HWState
type Capabilities (line 72) | struct Capabilities
FILE: src/capabilities.c
function nlongs (line 35) | static inline int nlongs(int nbit)
function getbit (line 40) | static inline int getbit(const unsigned long *map, int key)
function getabs (line 45) | static int getabs(struct input_absinfo *abs, int key, int fd)
function has_mt_data (line 52) | static int has_mt_data(const struct Capabilities *cap)
function has_integrated_button (line 57) | static int has_integrated_button(const struct Capabilities *cap)
function default_fuzz (line 69) | static void default_fuzz(struct Capabilities *cap, unsigned int code, in...
function read_capabilities (line 77) | int read_capabilities(struct Capabilities *cap, int fd)
function get_cap_xsize (line 137) | int get_cap_xsize(const struct Capabilities *cap)
function get_cap_ysize (line 143) | int get_cap_ysize(const struct Capabilities *cap)
function get_cap_wsize (line 149) | int get_cap_wsize(const struct Capabilities *cap)
function get_cap_xmid (line 155) | int get_cap_xmid(const struct Capabilities *cap)
function get_cap_ymid (line 161) | int get_cap_ymid(const struct Capabilities *cap)
function translate_cap_x (line 167) | int translate_cap_x(const struct Capabilities *cap, int x)
function translate_cap_y (line 173) | int translate_cap_y(const struct Capabilities *cap, int y)
function get_cap_xmin (line 179) | int get_cap_xmin(const struct Capabilities *cap)
function get_cap_ymin (line 185) | int get_cap_ymin(const struct Capabilities *cap)
function output_capabilities (line 191) | void output_capabilities(const struct Capabilities *cap)
FILE: src/gestures.c
function break_coasting (line 45) | static void break_coasting(struct Gestures* gs){
function trigger_button_up (line 49) | static void trigger_button_up(struct Gestures* gs, int button)
function trigger_button_down (line 61) | static void trigger_button_down(struct Gestures* gs, int button)
function trigger_button_emulation (line 77) | static void trigger_button_emulation(struct Gestures* gs, int button)
function trigger_button_emulation_end (line 92) | static void trigger_button_emulation_end(struct Gestures* gs)
function trigger_delayed_button_uncond (line 100) | int trigger_delayed_button_uncond(struct Gestures* gs)
function trigger_button_click (line 121) | static void trigger_button_click(struct Gestures* gs,
function reset_drag (line 150) | static void reset_drag(struct Gestures* gs){
function trigger_drag_ready (line 159) | static void trigger_drag_ready(struct Gestures* gs,
function trigger_drag_start (line 169) | static int trigger_drag_start(struct Gestures* gs,
function trigger_drag_stop (line 204) | static void trigger_drag_stop(struct Gestures* gs, const struct MConfig*...
function can_change_gesture_type (line 236) | static int can_change_gesture_type(struct Gestures* gs, int desired_gest...
function buttons_update (line 244) | static void buttons_update(struct Gestures* gs,
function touch_detect_update (line 321) | static void touch_detect_update(
function buttons_zone_update (line 366) | static int buttons_zone_update(
function abort_tapping (line 436) | static void abort_tapping(struct Gestures* gs, struct MTState* ms){
function tapping_update (line 454) | static void tapping_update(struct Gestures* gs,
function trigger_move (line 569) | static void trigger_move(struct Gestures* gs,
function get_swipe_dir_n (line 587) | static double get_swipe_dir_n(const struct Touch* touches[DIM_TOUCHES], ...
function get_swipe_avg_xy (line 614) | static void get_swipe_avg_xy(const struct Touch* touches[DIM_TOUCHES], i...
function get_button_for_dir (line 632) | int get_button_for_dir(const struct MConfigSwipe* cfg_swipe, int dir){
function trigger_swipe_unsafe (line 670) | static int trigger_swipe_unsafe(struct Gestures* gs,
function trigger_swipe (line 771) | static int trigger_swipe(struct Gestures* gs,
function trigger_edge (line 823) | static int trigger_edge(struct Gestures* gs, const struct MConfig* cfg,
function hypot_cmp (line 846) | static int hypot_cmp(int x, int y, int value)
function hypot_cmpf (line 861) | int hypot_cmpf(double x, double y, double value)
function is_touch_stationary (line 874) | static int is_touch_stationary(const struct Touch* touch, int max_movement)
function can_trigger_hold_move (line 880) | static int can_trigger_hold_move(const struct Gestures* gs,
function hold_move_gesture_to_touches (line 912) | static int hold_move_gesture_to_touches(int move_type, int real_touches_...
function is_hold_move (line 924) | static int is_hold_move(struct Gestures* gs)
function trigger_hold_move (line 935) | static int trigger_hold_move(struct Gestures* gs,
function calc_scale_dir (line 1027) | static int calc_scale_dir(const struct Touch* t0, const struct Touch* t1){
function trigger_scale (line 1046) | static int trigger_scale(struct Gestures* gs, const struct MConfig* cfg,
function trigger_rotate (line 1109) | static void trigger_rotate(struct Gestures* gs,
function trigger_reset (line 1137) | static void trigger_reset(struct Gestures* gs)
function get_rotate_dir (line 1148) | static int get_rotate_dir(const struct Touch* t1,
function moving_update (line 1162) | static void moving_update(struct Gestures* gs,
function dragging_update (line 1235) | static void dragging_update(struct Gestures* gs, const struct MConfig* cfg)
function is_timer_infinite (line 1243) | static int is_timer_infinite(struct Gestures* gs){
function delayed_update (line 1247) | static void delayed_update(struct Gestures* gs)
function gestures_init (line 1266) | void gestures_init(struct MTouch* mt)
function gestures_extract (line 1272) | void gestures_extract(struct MTouch* mt)
function gestures_delayed (line 1295) | int gestures_delayed(struct MTouch* mt)
FILE: src/hwstate.c
function hwstate_init (line 24) | void hwstate_init(struct HWState *s, const struct Capabilities *caps)
function finish_packet (line 34) | static void finish_packet(struct HWState *s, const struct Capabilities *...
function read_event (line 57) | static int read_event(struct HWState *s, const struct Capabilities *caps,
function hwstate_modify (line 121) | int hwstate_modify(struct HWState *s, struct mtdev *dev, int fd,
function find_finger (line 133) | int find_finger(const struct HWState *s, int tracking_id) {
FILE: src/mconfig.c
function mconfig_defaults (line 24) | void mconfig_defaults(struct MConfig* cfg)
function mconfig_init (line 142) | void mconfig_init(struct MConfig* cfg,
function mconfig_configure (line 193) | void mconfig_configure(struct MConfig* cfg,
FILE: src/mtouch.c
function mtouch_configure (line 27) | int mtouch_configure(struct MTouch* mt, int fd)
function mtouch_open (line 38) | int mtouch_open(struct MTouch* mt, int fd)
function mtouch_close (line 62) | int mtouch_close(struct MTouch* mt)
function mtouch_read (line 74) | int mtouch_read(struct MTouch* mt)
function mtouch_delayed (line 84) | int mtouch_delayed(struct MTouch* mt)
FILE: src/mtstate.c
function percentage (line 32) | static int inline percentage(int dividend, int divisor)
function touch_range_ratio (line 37) | static int inline touch_range_ratio(const struct MConfig* cfg, int value)
function pressure_range_ratio (line 42) | static int inline pressure_range_ratio(const struct MConfig* cfg, int va...
function finger_touch_ratio (line 47) | static int finger_touch_ratio(const struct MConfig* cfg, const struct Fi...
function is_touch (line 65) | static int is_touch(const struct MConfig* cfg,
function is_release (line 73) | static int is_release(const struct MConfig* cfg,
function is_thumb (line 79) | static int is_thumb(const struct MConfig* cfg,
function is_palm (line 102) | static int is_palm(const struct MConfig* cfg,
function touch_which_edge (line 139) | int touch_which_edge(const struct MConfig* cfg, const struct Touch* t)
function is_edge (line 165) | static int is_edge(const struct MConfig* cfg, const struct Touch* t)
function find_touch (line 172) | static int find_touch(struct MTState* ms,
function touch_append (line 185) | static int touch_append(struct MTState* ms,
function touch_update (line 220) | static void touch_update(struct MTState* ms,
function touch_release (line 247) | static void touch_release(struct MTState* ms,
function touches_invalidate (line 259) | static void touches_invalidate(struct MTState* ms)
function touches_update (line 268) | static void touches_update(struct MTState* ms,
function touches_clean (line 327) | static void touches_clean(struct MTState* ms)
function mtstate_output (line 338) | static void mtstate_output(const struct MTState* ms,
function mtstate_init (line 377) | void mtstate_init(struct MTState* ms)
function mtstate_extract (line 383) | void mtstate_extract(struct MTState* ms,
FILE: src/trig.c
function trig_encode_radians (line 28) | static double trig_encode_radians(double radians) {
function trig_decode_radians (line 37) | static double trig_decode_radians(double angle) {
function trig_direction (line 44) | double trig_direction(double dx, double dy) {
function trig_generalize (line 50) | int trig_generalize(double dir)
function trig_angles_add (line 64) | double trig_angles_add(double a1, double a2)
function trig_angles_sub (line 72) | double trig_angles_sub(double a1, double a2)
function trig_angles_acute (line 77) | double trig_angles_acute(double a1, double a2)
function trig_angles_avg (line 89) | double trig_angles_avg(double* angles, int len)
function trig_angles_cmp (line 102) | int trig_angles_cmp(double a1, double a2)
FILE: tools/mtrack-test.c
function xf86Msg (line 28) | void xf86Msg(int type, const char *format, ...)
type XF86OptionPtr (line 37) | typedef XF86OptionPtr pointer;
function xf86SetIntOption (line 40) | int xf86SetIntOption(XF86OptionPtr opts, const char *name, int deflt)
function xf86SetBoolOption (line 45) | int xf86SetBoolOption(XF86OptionPtr opts, const char *name, int deflt)
function xf86SetRealOption (line 50) | double xf86SetRealOption(XF86OptionPtr opts, const char *name, double de...
function print_gestures (line 55) | static void print_gestures(const struct Gestures* gs)
function loop_device (line 75) | static void loop_device(int fd)
function main (line 101) | int main(int argc, char *argv[])
Condensed preview — 44 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (292K chars).
[
{
"path": ".gitignore",
"chars": 351,
"preview": "*.o\n*.lo\n*.la\n*.swp\n*.dirstamp\n.deps/\n.libs/\nMakefile\nMakefile.in\n\n/m4\n/missing\n/libtool\ninstall-sh\nltmain.sh\n/aclocal.m"
},
{
"path": "COPYING",
"chars": 17989,
"preview": "\t\t GNU GENERAL PUBLIC LICENSE\n\t\t Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc."
},
{
"path": "CREDITS",
"chars": 2657,
"preview": "This is a copy of the CREDITS file from the xf86-input-multitouch driver.\n\n---\n\nMultitouch X driver (GPL license)\n\nCopyr"
},
{
"path": "Makefile.am",
"chars": 755,
"preview": "SOURCES_COMMON = \\\n\tsrc/capabilities.c \\\n\tsrc/gestures.c \\\n\tsrc/hwstate.c \\\n\tsrc/mconfig.c \\\n\tsrc/mtouch.c \\\n\tsrc/mtstat"
},
{
"path": "README.md",
"chars": 27639,
"preview": "xf86-input-mtrack\n=================\n###### v0.5.1\n\nAn Xorg driver for multitouch trackpads. Supports any trackpad whose "
},
{
"path": "RELEASE.md",
"chars": 1871,
"preview": "## v0.5.1\n* Add button emulation when no finger placement is valid\n* Add dedicated zone button\n* Enable the restriction "
},
{
"path": "configure.ac",
"chars": 3733,
"preview": "# Initialize Autoconf\nAC_PREREQ([2.60])\nAC_INIT([xf86-input-mtrack],\n\t[0.2.0],\n\t[https://bugs.freedesktop.org/enter_bug."
},
{
"path": "debian/README.Debian",
"chars": 96,
"preview": "Xorg Multitouch Trackpad Driver\n* Install the Debian package\n* Configure xorg.conf\n* Restart X\n\n"
},
{
"path": "debian/changelog",
"chars": 2950,
"preview": "xserver-xorg-input-mtrack (0.5.0) unstable; urgency=medium\n\n * Add tap-to-drag lock timeout\n * Make edge size configur"
},
{
"path": "debian/compat",
"chars": 2,
"preview": "5\n"
},
{
"path": "debian/control",
"chars": 559,
"preview": "Source: xserver-xorg-input-mtrack\nSection: misc\nPriority: optional\nMaintainer: Paweł Turkowski <p2rkw0@gmail.com>\nBuild-"
},
{
"path": "debian/copyright",
"chars": 1246,
"preview": "Source URL: https://github.com/p2rkw/xf86-input-mtrack\n\nUpstream Authors: Ryan Bourgeois <bluedragonx@gmail.com>\n "
},
{
"path": "debian/dirs",
"chars": 1,
"preview": "\n"
},
{
"path": "debian/rules",
"chars": 689,
"preview": "#!/usr/bin/make -f\n# -*- makefile -*-\n\n# Uncomment this to turn on verbose mode.\n#export DH_VERBOSE=1\n\nbuild-arch:\n\tdh_t"
},
{
"path": "driver/mprops.c",
"chars": 24927,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "driver/mtrack.c",
"chars": 19057,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "examples/acer-aspire-s3.conf",
"chars": 1610,
"preview": "Section \"InputClass\"\n MatchIsTouchpad \"on\"\n Identifier \"Touchpads\"\n Driver \"mtrack\"\n "
},
{
"path": "examples/asus-zenbook-ux330ua-ah55",
"chars": 12621,
"preview": "# mtrack config made for asus-zenbook-ux330ua-ah55 \n\n###----------------------------------------------------------------"
},
{
"path": "examples/dell-precision-5520.conf",
"chars": 1118,
"preview": "# Settings for Dell Precision 5520. Includes three-finger drag and reversed two finger scrolling.\nSection \"InputClass\"\n\t"
},
{
"path": "examples/dell-xps13-9333.conf",
"chars": 6380,
"preview": "# MatchIsTouchpad \"on\"\n#Section \"InputClass\"\n# Identifier \"Touchpads\"\n# Driver \"mtrack\"\n#EndSecti"
},
{
"path": "examples/lenovo-710s.conf",
"chars": 1120,
"preview": "Section \"InputClass\"\n MatchIsTouchpad \"true\"\n Identifier \"Touchpads\"\n Driver \"mtrack\"\n Option \"MaxTapT"
},
{
"path": "examples/lenovo-yoga-2-pro.conf",
"chars": 6243,
"preview": "## Works pretty well on Ubuntu 18.04 with deepin DE & Xfce\n\n########### 1. Install the mtrack driver ################\n#c"
},
{
"path": "examples/macbook-pro-retina-2013.conf",
"chars": 3621,
"preview": "Section \"InputClass\"\n MatchIsTouchpad \"on\"\n Identifier \"Touchpads\"\n MatchDevicePath \"/dev/inpu"
},
{
"path": "examples/macbook.conf",
"chars": 1629,
"preview": "# Taken from: https://howchoo.com/g/mdy0ngziogm/the-perfect-almost-touchpad-settings-on-linux-2\n\nSection \"InputClass\"\n "
},
{
"path": "include/button.h",
"chars": 1481,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "include/capabilities.h",
"chars": 1891,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "include/common.h",
"chars": 6060,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "include/gestures.h",
"chars": 3165,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "include/hwstate.h",
"chars": 1729,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "include/mconfig.h",
"chars": 11248,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "include/mprops.h",
"chars": 8420,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "include/mtouch.h",
"chars": 3302,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "include/mtstate.h",
"chars": 1965,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "include/trig.h",
"chars": 2405,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "required_packages.txt",
"chars": 51,
"preview": "xserver-xorg-dev mtdev-dev libmtdev-dev xutils-dev\n"
},
{
"path": "src/capabilities.c",
"chars": 6633,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "src/gestures.c",
"chars": 41486,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "src/hwstate.c",
"chars": 3900,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "src/mconfig.c",
"chars": 20954,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "src/mtouch.c",
"chars": 2170,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "src/mtstate.c",
"chars": 11138,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "src/trig.c",
"chars": 2673,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "tools/mtrack-test.c",
"chars": 2891,
"preview": "/***************************************************************************\n *\n * Multitouch X driver\n * Copyright (C) "
},
{
"path": "tools/reconfigure-xinput.sh",
"chars": 1003,
"preview": "#! /bin/bash\n\n# Script to parse configuration dumped by 'xinput --list-props <dev id>'\n# and reapply it on host machine."
}
]
About this extraction
This page contains the full source code of the p2rkw/xf86-input-mtrack GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 44 files (267.0 KB), approximately 76.2k tokens, and a symbol index with 221 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.