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://www.diagrams.net).
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
45static inline const char*
46middlebutton_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
64static inline const char*
65middlebutton_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
80static void
81middlebutton_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
90static void
91middlebutton_timer_set(struct evdev_device *device, uint64_t now)
92{
93	libinput_timer_set(&device->middlebutton.timer,
94			   now + MIDDLEBUTTON_TIMEOUT);
95}
96
97static void
98middlebutton_timer_cancel(struct evdev_device *device)
99{
100	libinput_timer_cancel(&device->middlebutton.timer);
101}
102
103static inline void
104middlebutton_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
129static void
130middlebutton_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
141static int
142evdev_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
167static int
168evdev_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
220static int
221evdev_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
274static int
275evdev_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
317static int
318evdev_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
352static int
353evdev_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
387static int
388evdev_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
410static int
411evdev_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
439static int
440evdev_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}
466static int
467evdev_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
494static int
495evdev_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
564static inline void
565evdev_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
577bool
578evdev_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 btnbit = (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	    btnbit >= 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 |= bit(btnbit);
628	else
629		device->middlebutton.button_mask &= ~bit(btnbit);
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
642static void
643evdev_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
650int
651evdev_middlebutton_is_available(struct libinput_device *device)
652{
653	return 1;
654}
655
656static enum libinput_config_status
657evdev_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
678enum libinput_config_middle_emulation_state
679evdev_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
688enum libinput_config_middle_emulation_state
689evdev_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
698void
699evdev_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