touchpad: Add clickpad-style software buttons
[platform/upstream/libinput.git] / src / evdev-mt-touchpad.h
1 /*
2  * Copyright © 2014 Red Hat, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23
24 #ifndef EVDEV_MT_TOUCHPAD_H
25 #define EVDEV_MT_TOUCHPAD_H
26
27 #include <stdbool.h>
28
29 #include "evdev.h"
30 #include "filter.h"
31
32 #define TOUCHPAD_HISTORY_LENGTH 4
33 #define TOUCHPAD_MIN_SAMPLES 4
34
35 enum touchpad_event {
36         TOUCHPAD_EVENT_NONE             = 0,
37         TOUCHPAD_EVENT_MOTION           = (1 << 0),
38         TOUCHPAD_EVENT_BUTTON_PRESS     = (1 << 1),
39         TOUCHPAD_EVENT_BUTTON_RELEASE   = (1 << 2),
40 };
41
42 enum touch_state {
43         TOUCH_NONE = 0,
44         TOUCH_BEGIN,
45         TOUCH_UPDATE,
46         TOUCH_END
47 };
48
49 enum button_event {
50        BUTTON_EVENT_IN_BOTTOM_R = 30,
51        BUTTON_EVENT_IN_BOTTOM_L,
52        BUTTON_EVENT_IN_AREA,
53        BUTTON_EVENT_UP,
54        BUTTON_EVENT_PRESS,
55        BUTTON_EVENT_RELEASE,
56        BUTTON_EVENT_TIMEOUT,
57 };
58
59 enum button_state {
60        BUTTON_STATE_NONE,
61        BUTTON_STATE_AREA,
62        BUTTON_STATE_BOTTOM,
63        BUTTON_STATE_BOTTOM_NEW,
64        BUTTON_STATE_BOTTOM_TO_AREA,
65 };
66
67 enum scroll_state {
68         SCROLL_STATE_NONE,
69         SCROLL_STATE_SCROLLING
70 };
71
72 enum tp_tap_state {
73         TAP_STATE_IDLE = 4,
74         TAP_STATE_TOUCH,
75         TAP_STATE_HOLD,
76         TAP_STATE_TAPPED,
77         TAP_STATE_TOUCH_2,
78         TAP_STATE_TOUCH_2_HOLD,
79         TAP_STATE_TOUCH_3,
80         TAP_STATE_TOUCH_3_HOLD,
81         TAP_STATE_DRAGGING_OR_DOUBLETAP,
82         TAP_STATE_DRAGGING,
83         TAP_STATE_DRAGGING_WAIT,
84         TAP_STATE_DRAGGING_2,
85         TAP_STATE_DEAD, /**< finger count exceeded */
86 };
87
88 struct tp_motion {
89         int32_t x;
90         int32_t y;
91 };
92
93 struct tp_touch {
94         enum touch_state state;
95         bool dirty;
96         bool fake;                              /* a fake touch */
97         bool is_pointer;                        /* the pointer-controlling touch */
98         int32_t x;
99         int32_t y;
100         uint32_t millis;
101
102         struct {
103                 struct tp_motion samples[TOUCHPAD_HISTORY_LENGTH];
104                 unsigned int index;
105                 unsigned int count;
106         } history;
107
108         struct {
109                 int32_t center_x;
110                 int32_t center_y;
111         } hysteresis;
112
113         /* A pinned touchpoint is the one that pressed the physical button
114          * on a clickpad. After the release, it won't move until the center
115          * moves more than a threshold away from the original coordinates
116          */
117         struct {
118                 bool is_pinned;
119                 int32_t center_x;
120                 int32_t center_y;
121         } pinned;
122
123         /* Software-button state and timeout if applicable */
124         struct {
125                 enum button_state state;
126                 /* We use button_event here so we can use == on events */
127                 enum button_event curr;
128                 uint32_t timeout;
129         } button;
130 };
131
132 struct tp_dispatch {
133         struct evdev_dispatch base;
134         struct evdev_device *device;
135         unsigned int nfingers_down;             /* number of fingers down */
136         unsigned int slot;                      /* current slot */
137         bool has_mt;
138
139         unsigned int ntouches;                  /* number of slots */
140         struct tp_touch *touches;               /* len == ntouches */
141         unsigned int fake_touches;              /* fake touch mask */
142
143         struct {
144                 int32_t margin_x;
145                 int32_t margin_y;
146         } hysteresis;
147
148         struct motion_filter *filter;
149
150         struct {
151                 double constant_factor;
152                 double min_factor;
153                 double max_factor;
154         } accel;
155
156         struct {
157                 bool has_buttons;               /* true for physical LMR buttons */
158                 bool use_clickfinger;           /* number of fingers decides button number */
159                 bool use_softbuttons;           /* use software-button area */
160                 uint32_t state;
161                 uint32_t old_state;
162                 uint32_t motion_dist;           /* for pinned touches */
163                 unsigned int active;            /* currently active button, for release event */
164
165                 /* Only used if has_buttons is false. The software button area is always
166                  * a horizontal strip across the touchpad. Depending on the
167                  * rightbutton_left_edge value, the buttons are split according to the
168                  * edge settings.
169                   */
170                 struct {
171                         int32_t top_edge;
172                         int32_t rightbutton_left_edge;
173                 } area;
174
175                 unsigned int timeout;           /* current timeout in ms */
176
177                 int timer_fd;
178                 struct libinput_source *source;
179         } buttons;                              /* physical buttons */
180
181         struct {
182                 enum scroll_state state;
183                 enum libinput_pointer_axis direction;
184         } scroll;
185
186         enum touchpad_event queued;
187
188         struct {
189                 bool enabled;
190                 int timer_fd;
191                 struct libinput_source *source;
192                 unsigned int timeout;
193                 enum tp_tap_state state;
194         } tap;
195 };
196
197 #define tp_for_each_touch(_tp, _t) \
198         for (unsigned int _i = 0; _i < (_tp)->ntouches && (_t = &(_tp)->touches[_i]); _i++)
199
200 void
201 tp_get_delta(struct tp_touch *t, double *dx, double *dy);
202
203 int
204 tp_tap_handle_state(struct tp_dispatch *tp, uint32_t time);
205
206 unsigned int
207 tp_tap_handle_timeout(struct tp_dispatch *tp, uint32_t time);
208
209 int
210 tp_init_tap(struct tp_dispatch *tp);
211
212 void
213 tp_destroy_tap(struct tp_dispatch *tp);
214
215 int
216 tp_init_buttons(struct tp_dispatch *tp, struct evdev_device *device);
217
218 void
219 tp_destroy_buttons(struct tp_dispatch *tp);
220
221 int
222 tp_process_button(struct tp_dispatch *tp,
223                   const struct input_event *e,
224                   uint32_t time);
225
226 int
227 tp_post_button_events(struct tp_dispatch *tp, uint32_t time);
228
229 int
230 tp_button_handle_state(struct tp_dispatch *tp, uint32_t time);
231
232 #endif