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