1 /*
2 * Copyright © 2014-2015 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "config.h"
25
26 #include <stdint.h>
27
28 #include "evdev.h"
29
30 #define MIDDLEBUTTON_TIMEOUT ms2us(50)
31
32 /*****************************************
33 * BEFORE YOU EDIT THIS FILE, look at the state diagram in
34 * doc/middle-button-emulation-state-machine.svg, or online at
35 * https://drive.google.com/file/d/0B1NwWmji69nodUJncXRMc1FvY1k/view?usp=sharing
36 * (it's a http://draw.io diagram)
37 *
38 * Any changes in this file must be represented in the diagram.
39 *
40 * Note in regards to the state machine: it only handles left, right and
41 * emulated middle button clicks, all other button events are passed
42 * through. When in the PASSTHROUGH state, all events are passed through
43 * as-is.
44 */
45
46 static inline const char*
middlebutton_state_to_str(enum evdev_middlebutton_state state)47 middlebutton_state_to_str(enum evdev_middlebutton_state state)
48 {
49 switch (state) {
50 CASE_RETURN_STRING(MIDDLEBUTTON_IDLE);
51 CASE_RETURN_STRING(MIDDLEBUTTON_LEFT_DOWN);
52 CASE_RETURN_STRING(MIDDLEBUTTON_RIGHT_DOWN);
53 CASE_RETURN_STRING(MIDDLEBUTTON_MIDDLE);
54 CASE_RETURN_STRING(MIDDLEBUTTON_LEFT_UP_PENDING);
55 CASE_RETURN_STRING(MIDDLEBUTTON_RIGHT_UP_PENDING);
56 CASE_RETURN_STRING(MIDDLEBUTTON_PASSTHROUGH);
57 CASE_RETURN_STRING(MIDDLEBUTTON_IGNORE_LR);
58 CASE_RETURN_STRING(MIDDLEBUTTON_IGNORE_L);
59 CASE_RETURN_STRING(MIDDLEBUTTON_IGNORE_R);
60 }
61
62 return NULL;
63 }
64
65 static inline const char*
middlebutton_event_to_str(enum evdev_middlebutton_event event)66 middlebutton_event_to_str(enum evdev_middlebutton_event event)
67 {
68 switch (event) {
69 CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_L_DOWN);
70 CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_R_DOWN);
71 CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_OTHER);
72 CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_L_UP);
73 CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_R_UP);
74 CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_TIMEOUT);
75 CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_ALL_UP);
76 }
77
78 return NULL;
79 }
80
81 static void
middlebutton_state_error(struct evdev_device * device,enum evdev_middlebutton_event event)82 middlebutton_state_error(struct evdev_device *device,
83 enum evdev_middlebutton_event event)
84 {
85 evdev_log_bug_libinput(device,
86 "Invalid event %s in middle btn state %s\n",
87 middlebutton_event_to_str(event),
88 middlebutton_state_to_str(device->middlebutton.state));
89 }
90
91 static void
middlebutton_timer_set(struct evdev_device * device,uint64_t now)92 middlebutton_timer_set(struct evdev_device *device, uint64_t now)
93 {
94 libinput_timer_set(&device->middlebutton.timer,
95 now + MIDDLEBUTTON_TIMEOUT);
96 }
97
98 static void
middlebutton_timer_cancel(struct evdev_device * device)99 middlebutton_timer_cancel(struct evdev_device *device)
100 {
101 libinput_timer_cancel(&device->middlebutton.timer);
102 }
103
104 static inline void
middlebutton_set_state(struct evdev_device * device,enum evdev_middlebutton_state state,uint64_t now)105 middlebutton_set_state(struct evdev_device *device,
106 enum evdev_middlebutton_state state,
107 uint64_t now)
108 {
109 switch (state) {
110 case MIDDLEBUTTON_LEFT_DOWN:
111 case MIDDLEBUTTON_RIGHT_DOWN:
112 middlebutton_timer_set(device, now);
113 device->middlebutton.first_event_time = now;
114 break;
115 case MIDDLEBUTTON_IDLE:
116 case MIDDLEBUTTON_MIDDLE:
117 case MIDDLEBUTTON_LEFT_UP_PENDING:
118 case MIDDLEBUTTON_RIGHT_UP_PENDING:
119 case MIDDLEBUTTON_PASSTHROUGH:
120 case MIDDLEBUTTON_IGNORE_LR:
121 case MIDDLEBUTTON_IGNORE_L:
122 case MIDDLEBUTTON_IGNORE_R:
123 middlebutton_timer_cancel(device);
124 break;
125 }
126
127 device->middlebutton.state = state;
128 }
129
130 static void
middlebutton_post_event(struct evdev_device * device,uint64_t now,int button,enum libinput_button_state state)131 middlebutton_post_event(struct evdev_device *device,
132 uint64_t now,
133 int button,
134 enum libinput_button_state state)
135 {
136 evdev_pointer_notify_button(device,
137 now,
138 button,
139 state);
140 }
141
142 static int
evdev_middlebutton_idle_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)143 evdev_middlebutton_idle_handle_event(struct evdev_device *device,
144 uint64_t time,
145 enum evdev_middlebutton_event event)
146 {
147 switch (event) {
148 case MIDDLEBUTTON_EVENT_L_DOWN:
149 middlebutton_set_state(device, MIDDLEBUTTON_LEFT_DOWN, time);
150 break;
151 case MIDDLEBUTTON_EVENT_R_DOWN:
152 middlebutton_set_state(device, MIDDLEBUTTON_RIGHT_DOWN, time);
153 break;
154 case MIDDLEBUTTON_EVENT_OTHER:
155 return 0;
156 case MIDDLEBUTTON_EVENT_R_UP:
157 case MIDDLEBUTTON_EVENT_L_UP:
158 case MIDDLEBUTTON_EVENT_TIMEOUT:
159 middlebutton_state_error(device, event);
160 break;
161 case MIDDLEBUTTON_EVENT_ALL_UP:
162 break;
163 }
164
165 return 1;
166 }
167
168 static int
evdev_middlebutton_ldown_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)169 evdev_middlebutton_ldown_handle_event(struct evdev_device *device,
170 uint64_t time,
171 enum evdev_middlebutton_event event)
172 {
173 switch (event) {
174 case MIDDLEBUTTON_EVENT_L_DOWN:
175 middlebutton_state_error(device, event);
176 break;
177 case MIDDLEBUTTON_EVENT_R_DOWN:
178 middlebutton_post_event(device, time,
179 BTN_MIDDLE,
180 LIBINPUT_BUTTON_STATE_PRESSED);
181 middlebutton_set_state(device, MIDDLEBUTTON_MIDDLE, time);
182 break;
183 case MIDDLEBUTTON_EVENT_OTHER:
184 middlebutton_post_event(device, time,
185 BTN_LEFT,
186 LIBINPUT_BUTTON_STATE_PRESSED);
187 middlebutton_set_state(device,
188 MIDDLEBUTTON_PASSTHROUGH,
189 time);
190 return 0;
191 case MIDDLEBUTTON_EVENT_R_UP:
192 middlebutton_state_error(device, event);
193 break;
194 case MIDDLEBUTTON_EVENT_L_UP:
195 middlebutton_post_event(device,
196 device->middlebutton.first_event_time,
197 BTN_LEFT,
198 LIBINPUT_BUTTON_STATE_PRESSED);
199 middlebutton_post_event(device, time,
200 BTN_LEFT,
201 LIBINPUT_BUTTON_STATE_RELEASED);
202 middlebutton_set_state(device, MIDDLEBUTTON_IDLE, time);
203 break;
204 case MIDDLEBUTTON_EVENT_TIMEOUT:
205 middlebutton_post_event(device,
206 device->middlebutton.first_event_time,
207 BTN_LEFT,
208 LIBINPUT_BUTTON_STATE_PRESSED);
209 middlebutton_set_state(device,
210 MIDDLEBUTTON_PASSTHROUGH,
211 time);
212 break;
213 case MIDDLEBUTTON_EVENT_ALL_UP:
214 middlebutton_state_error(device, event);
215 break;
216 }
217
218 return 1;
219 }
220
221 static int
evdev_middlebutton_rdown_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)222 evdev_middlebutton_rdown_handle_event(struct evdev_device *device,
223 uint64_t time,
224 enum evdev_middlebutton_event event)
225 {
226 switch (event) {
227 case MIDDLEBUTTON_EVENT_L_DOWN:
228 middlebutton_post_event(device, time,
229 BTN_MIDDLE,
230 LIBINPUT_BUTTON_STATE_PRESSED);
231 middlebutton_set_state(device, MIDDLEBUTTON_MIDDLE, time);
232 break;
233 case MIDDLEBUTTON_EVENT_R_DOWN:
234 middlebutton_state_error(device, event);
235 break;
236 case MIDDLEBUTTON_EVENT_OTHER:
237 middlebutton_post_event(device,
238 device->middlebutton.first_event_time,
239 BTN_RIGHT,
240 LIBINPUT_BUTTON_STATE_PRESSED);
241 middlebutton_set_state(device,
242 MIDDLEBUTTON_PASSTHROUGH,
243 time);
244 return 0;
245 case MIDDLEBUTTON_EVENT_R_UP:
246 middlebutton_post_event(device,
247 device->middlebutton.first_event_time,
248 BTN_RIGHT,
249 LIBINPUT_BUTTON_STATE_PRESSED);
250 middlebutton_post_event(device, time,
251 BTN_RIGHT,
252 LIBINPUT_BUTTON_STATE_RELEASED);
253 middlebutton_set_state(device, MIDDLEBUTTON_IDLE, time);
254 break;
255 case MIDDLEBUTTON_EVENT_L_UP:
256 middlebutton_state_error(device, event);
257 break;
258 case MIDDLEBUTTON_EVENT_TIMEOUT:
259 middlebutton_post_event(device,
260 device->middlebutton.first_event_time,
261 BTN_RIGHT,
262 LIBINPUT_BUTTON_STATE_PRESSED);
263 middlebutton_set_state(device,
264 MIDDLEBUTTON_PASSTHROUGH,
265 time);
266 break;
267 case MIDDLEBUTTON_EVENT_ALL_UP:
268 middlebutton_state_error(device, event);
269 break;
270 }
271
272 return 1;
273 }
274
275 static int
evdev_middlebutton_middle_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)276 evdev_middlebutton_middle_handle_event(struct evdev_device *device,
277 uint64_t time,
278 enum evdev_middlebutton_event event)
279 {
280 switch (event) {
281 case MIDDLEBUTTON_EVENT_L_DOWN:
282 case MIDDLEBUTTON_EVENT_R_DOWN:
283 middlebutton_state_error(device, event);
284 break;
285 case MIDDLEBUTTON_EVENT_OTHER:
286 middlebutton_post_event(device, time,
287 BTN_MIDDLE,
288 LIBINPUT_BUTTON_STATE_RELEASED);
289 middlebutton_set_state(device, MIDDLEBUTTON_IGNORE_LR, time);
290 return 0;
291 case MIDDLEBUTTON_EVENT_R_UP:
292 middlebutton_post_event(device, time,
293 BTN_MIDDLE,
294 LIBINPUT_BUTTON_STATE_RELEASED);
295 middlebutton_set_state(device,
296 MIDDLEBUTTON_LEFT_UP_PENDING,
297 time);
298 break;
299 case MIDDLEBUTTON_EVENT_L_UP:
300 middlebutton_post_event(device, time,
301 BTN_MIDDLE,
302 LIBINPUT_BUTTON_STATE_RELEASED);
303 middlebutton_set_state(device,
304 MIDDLEBUTTON_RIGHT_UP_PENDING,
305 time);
306 break;
307 case MIDDLEBUTTON_EVENT_TIMEOUT:
308 middlebutton_state_error(device, event);
309 break;
310 case MIDDLEBUTTON_EVENT_ALL_UP:
311 middlebutton_state_error(device, event);
312 break;
313 }
314
315 return 1;
316 }
317
318 static int
evdev_middlebutton_lup_pending_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)319 evdev_middlebutton_lup_pending_handle_event(struct evdev_device *device,
320 uint64_t time,
321 enum evdev_middlebutton_event event)
322 {
323 switch (event) {
324 case MIDDLEBUTTON_EVENT_L_DOWN:
325 middlebutton_state_error(device, event);
326 break;
327 case MIDDLEBUTTON_EVENT_R_DOWN:
328 middlebutton_post_event(device, time,
329 BTN_MIDDLE,
330 LIBINPUT_BUTTON_STATE_PRESSED);
331 middlebutton_set_state(device, MIDDLEBUTTON_MIDDLE, time);
332 break;
333 case MIDDLEBUTTON_EVENT_OTHER:
334 middlebutton_set_state(device, MIDDLEBUTTON_IGNORE_L, time);
335 return 0;
336 case MIDDLEBUTTON_EVENT_R_UP:
337 middlebutton_state_error(device, event);
338 break;
339 case MIDDLEBUTTON_EVENT_L_UP:
340 middlebutton_set_state(device, MIDDLEBUTTON_IDLE, time);
341 break;
342 case MIDDLEBUTTON_EVENT_TIMEOUT:
343 middlebutton_state_error(device, event);
344 break;
345 case MIDDLEBUTTON_EVENT_ALL_UP:
346 middlebutton_state_error(device, event);
347 break;
348 }
349
350 return 1;
351 }
352
353 static int
evdev_middlebutton_rup_pending_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)354 evdev_middlebutton_rup_pending_handle_event(struct evdev_device *device,
355 uint64_t time,
356 enum evdev_middlebutton_event event)
357 {
358 switch (event) {
359 case MIDDLEBUTTON_EVENT_L_DOWN:
360 middlebutton_post_event(device, time,
361 BTN_MIDDLE,
362 LIBINPUT_BUTTON_STATE_PRESSED);
363 middlebutton_set_state(device, MIDDLEBUTTON_MIDDLE, time);
364 break;
365 case MIDDLEBUTTON_EVENT_R_DOWN:
366 middlebutton_state_error(device, event);
367 break;
368 case MIDDLEBUTTON_EVENT_OTHER:
369 middlebutton_set_state(device, MIDDLEBUTTON_IGNORE_R, time);
370 return 0;
371 case MIDDLEBUTTON_EVENT_R_UP:
372 middlebutton_set_state(device, MIDDLEBUTTON_IDLE, time);
373 break;
374 case MIDDLEBUTTON_EVENT_L_UP:
375 middlebutton_state_error(device, event);
376 break;
377 case MIDDLEBUTTON_EVENT_TIMEOUT:
378 middlebutton_state_error(device, event);
379 break;
380 case MIDDLEBUTTON_EVENT_ALL_UP:
381 middlebutton_state_error(device, event);
382 break;
383 }
384
385 return 1;
386 }
387
388 static int
evdev_middlebutton_passthrough_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)389 evdev_middlebutton_passthrough_handle_event(struct evdev_device *device,
390 uint64_t time,
391 enum evdev_middlebutton_event event)
392 {
393 switch (event) {
394 case MIDDLEBUTTON_EVENT_L_DOWN:
395 case MIDDLEBUTTON_EVENT_R_DOWN:
396 case MIDDLEBUTTON_EVENT_OTHER:
397 case MIDDLEBUTTON_EVENT_R_UP:
398 case MIDDLEBUTTON_EVENT_L_UP:
399 return 0;
400 case MIDDLEBUTTON_EVENT_TIMEOUT:
401 middlebutton_state_error(device, event);
402 break;
403 case MIDDLEBUTTON_EVENT_ALL_UP:
404 middlebutton_set_state(device, MIDDLEBUTTON_IDLE, time);
405 break;
406 }
407
408 return 1;
409 }
410
411 static int
evdev_middlebutton_ignore_lr_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)412 evdev_middlebutton_ignore_lr_handle_event(struct evdev_device *device,
413 uint64_t time,
414 enum evdev_middlebutton_event event)
415 {
416 switch (event) {
417 case MIDDLEBUTTON_EVENT_L_DOWN:
418 case MIDDLEBUTTON_EVENT_R_DOWN:
419 middlebutton_state_error(device, event);
420 break;
421 case MIDDLEBUTTON_EVENT_OTHER:
422 return 0;
423 case MIDDLEBUTTON_EVENT_R_UP:
424 middlebutton_set_state(device, MIDDLEBUTTON_IGNORE_L, time);
425 break;
426 case MIDDLEBUTTON_EVENT_L_UP:
427 middlebutton_set_state(device, MIDDLEBUTTON_IGNORE_R, time);
428 break;
429 case MIDDLEBUTTON_EVENT_TIMEOUT:
430 middlebutton_state_error(device, event);
431 break;
432 case MIDDLEBUTTON_EVENT_ALL_UP:
433 middlebutton_state_error(device, event);
434 break;
435 }
436
437 return 1;
438 }
439
440 static int
evdev_middlebutton_ignore_l_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)441 evdev_middlebutton_ignore_l_handle_event(struct evdev_device *device,
442 uint64_t time,
443 enum evdev_middlebutton_event event)
444 {
445 switch (event) {
446 case MIDDLEBUTTON_EVENT_L_DOWN:
447 middlebutton_state_error(device, event);
448 break;
449 case MIDDLEBUTTON_EVENT_R_DOWN:
450 return 0;
451 case MIDDLEBUTTON_EVENT_OTHER:
452 case MIDDLEBUTTON_EVENT_R_UP:
453 return 0;
454 case MIDDLEBUTTON_EVENT_L_UP:
455 middlebutton_set_state(device,
456 MIDDLEBUTTON_PASSTHROUGH,
457 time);
458 break;
459 case MIDDLEBUTTON_EVENT_TIMEOUT:
460 case MIDDLEBUTTON_EVENT_ALL_UP:
461 middlebutton_state_error(device, event);
462 break;
463 }
464
465 return 1;
466 }
467 static int
evdev_middlebutton_ignore_r_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)468 evdev_middlebutton_ignore_r_handle_event(struct evdev_device *device,
469 uint64_t time,
470 enum evdev_middlebutton_event event)
471 {
472 switch (event) {
473 case MIDDLEBUTTON_EVENT_L_DOWN:
474 return 0;
475 case MIDDLEBUTTON_EVENT_R_DOWN:
476 middlebutton_state_error(device, event);
477 break;
478 case MIDDLEBUTTON_EVENT_OTHER:
479 return 0;
480 case MIDDLEBUTTON_EVENT_R_UP:
481 middlebutton_set_state(device,
482 MIDDLEBUTTON_PASSTHROUGH,
483 time);
484 break;
485 case MIDDLEBUTTON_EVENT_L_UP:
486 return 0;
487 case MIDDLEBUTTON_EVENT_TIMEOUT:
488 case MIDDLEBUTTON_EVENT_ALL_UP:
489 break;
490 }
491
492 return 1;
493 }
494
495 static int
evdev_middlebutton_handle_event(struct evdev_device * device,uint64_t time,enum evdev_middlebutton_event event)496 evdev_middlebutton_handle_event(struct evdev_device *device,
497 uint64_t time,
498 enum evdev_middlebutton_event event)
499 {
500 int rc = 0;
501 enum evdev_middlebutton_state current;
502
503 current = device->middlebutton.state;
504
505 switch (current) {
506 case MIDDLEBUTTON_IDLE:
507 rc = evdev_middlebutton_idle_handle_event(device, time, event);
508 break;
509 case MIDDLEBUTTON_LEFT_DOWN:
510 rc = evdev_middlebutton_ldown_handle_event(device, time, event);
511 break;
512 case MIDDLEBUTTON_RIGHT_DOWN:
513 rc = evdev_middlebutton_rdown_handle_event(device, time, event);
514 break;
515 case MIDDLEBUTTON_MIDDLE:
516 rc = evdev_middlebutton_middle_handle_event(device, time, event);
517 break;
518 case MIDDLEBUTTON_LEFT_UP_PENDING:
519 rc = evdev_middlebutton_lup_pending_handle_event(device,
520 time,
521 event);
522 break;
523 case MIDDLEBUTTON_RIGHT_UP_PENDING:
524 rc = evdev_middlebutton_rup_pending_handle_event(device,
525 time,
526 event);
527 break;
528 case MIDDLEBUTTON_PASSTHROUGH:
529 rc = evdev_middlebutton_passthrough_handle_event(device,
530 time,
531 event);
532 break;
533 case MIDDLEBUTTON_IGNORE_LR:
534 rc = evdev_middlebutton_ignore_lr_handle_event(device,
535 time,
536 event);
537 break;
538 case MIDDLEBUTTON_IGNORE_L:
539 rc = evdev_middlebutton_ignore_l_handle_event(device,
540 time,
541 event);
542 break;
543 case MIDDLEBUTTON_IGNORE_R:
544 rc = evdev_middlebutton_ignore_r_handle_event(device,
545 time,
546 event);
547 break;
548 default:
549 evdev_log_bug_libinput(device,
550 "Invalid middle button state %d\n",
551 current);
552 break;
553 }
554
555 evdev_log_debug(device,
556 "middlebuttonstate: %s → %s → %s, rc %d\n",
557 middlebutton_state_to_str(current),
558 middlebutton_event_to_str(event),
559 middlebutton_state_to_str(device->middlebutton.state),
560 rc);
561
562 return rc;
563 }
564
565 static inline void
evdev_middlebutton_apply_config(struct evdev_device * device)566 evdev_middlebutton_apply_config(struct evdev_device *device)
567 {
568 if (device->middlebutton.want_enabled ==
569 device->middlebutton.enabled)
570 return;
571
572 if (device->middlebutton.button_mask != 0)
573 return;
574
575 device->middlebutton.enabled = device->middlebutton.want_enabled;
576 }
577
578 bool
evdev_middlebutton_filter_button(struct evdev_device * device,uint64_t time,int button,enum libinput_button_state state)579 evdev_middlebutton_filter_button(struct evdev_device *device,
580 uint64_t time,
581 int button,
582 enum libinput_button_state state)
583 {
584 enum evdev_middlebutton_event event;
585 bool is_press = state == LIBINPUT_BUTTON_STATE_PRESSED;
586 int rc;
587 unsigned int bit = (button - BTN_LEFT);
588 uint32_t old_mask = 0;
589
590 if (!device->middlebutton.enabled)
591 return false;
592
593 switch (button) {
594 case BTN_LEFT:
595 if (is_press)
596 event = MIDDLEBUTTON_EVENT_L_DOWN;
597 else
598 event = MIDDLEBUTTON_EVENT_L_UP;
599 break;
600 case BTN_RIGHT:
601 if (is_press)
602 event = MIDDLEBUTTON_EVENT_R_DOWN;
603 else
604 event = MIDDLEBUTTON_EVENT_R_UP;
605 break;
606
607 /* BTN_MIDDLE counts as "other" and resets middle button
608 * emulation */
609 case BTN_MIDDLE:
610 default:
611 event = MIDDLEBUTTON_EVENT_OTHER;
612 break;
613 }
614
615 if (button < BTN_LEFT ||
616 bit >= sizeof(device->middlebutton.button_mask) * 8) {
617 evdev_log_bug_libinput(device,
618 "Button mask too small for %s\n",
619 libevdev_event_code_get_name(EV_KEY,
620 button));
621 return true;
622 }
623
624 rc = evdev_middlebutton_handle_event(device, time, event);
625
626 old_mask = device->middlebutton.button_mask;
627 if (is_press)
628 device->middlebutton.button_mask |= 1 << bit;
629 else
630 device->middlebutton.button_mask &= ~(1 << bit);
631
632 if (old_mask != device->middlebutton.button_mask &&
633 device->middlebutton.button_mask == 0) {
634 evdev_middlebutton_handle_event(device,
635 time,
636 MIDDLEBUTTON_EVENT_ALL_UP);
637 evdev_middlebutton_apply_config(device);
638 }
639
640 return rc;
641 }
642
643 static void
evdev_middlebutton_handle_timeout(uint64_t now,void * data)644 evdev_middlebutton_handle_timeout(uint64_t now, void *data)
645 {
646 struct evdev_device *device = evdev_device(data);
647
648 evdev_middlebutton_handle_event(device, now, MIDDLEBUTTON_EVENT_TIMEOUT);
649 }
650
651 int
evdev_middlebutton_is_available(struct libinput_device * device)652 evdev_middlebutton_is_available(struct libinput_device *device)
653 {
654 return 1;
655 }
656
657 static enum libinput_config_status
evdev_middlebutton_set(struct libinput_device * device,enum libinput_config_middle_emulation_state enable)658 evdev_middlebutton_set(struct libinput_device *device,
659 enum libinput_config_middle_emulation_state enable)
660 {
661 struct evdev_device *evdev = evdev_device(device);
662
663 switch (enable) {
664 case LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED:
665 evdev->middlebutton.want_enabled = true;
666 break;
667 case LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED:
668 evdev->middlebutton.want_enabled = false;
669 break;
670 default:
671 return LIBINPUT_CONFIG_STATUS_INVALID;
672 }
673
674 evdev_middlebutton_apply_config(evdev);
675
676 return LIBINPUT_CONFIG_STATUS_SUCCESS;
677 }
678
679 enum libinput_config_middle_emulation_state
evdev_middlebutton_get(struct libinput_device * device)680 evdev_middlebutton_get(struct libinput_device *device)
681 {
682 struct evdev_device *evdev = evdev_device(device);
683
684 return evdev->middlebutton.want_enabled ?
685 LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED :
686 LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
687 }
688
689 enum libinput_config_middle_emulation_state
evdev_middlebutton_get_default(struct libinput_device * device)690 evdev_middlebutton_get_default(struct libinput_device *device)
691 {
692 struct evdev_device *evdev = evdev_device(device);
693
694 return evdev->middlebutton.enabled_default ?
695 LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED :
696 LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
697 }
698
699 void
evdev_init_middlebutton(struct evdev_device * device,bool enable,bool want_config)700 evdev_init_middlebutton(struct evdev_device *device,
701 bool enable,
702 bool want_config)
703 {
704 char timer_name[64];
705
706 snprintf(timer_name,
707 sizeof(timer_name),
708 "%s middlebutton",
709 evdev_device_get_sysname(device));
710 libinput_timer_init(&device->middlebutton.timer,
711 evdev_libinput_context(device),
712 timer_name,
713 evdev_middlebutton_handle_timeout,
714 device);
715 device->middlebutton.enabled_default = enable;
716 device->middlebutton.want_enabled = enable;
717 device->middlebutton.enabled = enable;
718
719 if (!want_config)
720 return;
721
722 device->middlebutton.config.available = evdev_middlebutton_is_available;
723 device->middlebutton.config.set = evdev_middlebutton_set;
724 device->middlebutton.config.get = evdev_middlebutton_get;
725 device->middlebutton.config.get_default = evdev_middlebutton_get_default;
726 device->base.config.middle_emulation = &device->middlebutton.config;
727 }
728