• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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