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