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