#![allow(dead_code)]
use crate::{
ButtonId, ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, VirtualKeyCode,
};
use libc::{input_event, timeval};
use std::convert::{TryFrom, TryInto};
use std::fmt::{self, Debug, Display};
use std::fs::{self, File};
use std::io::{ErrorKind, Read};
use std::os::unix::io::{AsRawFd, RawFd};
use std::path::Path;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
const EV_SYN: u16 = 0x00;
const EV_KEY: u16 = 0x01;
const EV_REL: u16 = 0x02;
const EV_ABS: u16 = 0x03;
const EV_MSC: u16 = 0x04;
const EV_SW: u16 = 0x05;
const EV_LED: u16 = 0x11;
const EV_SND: u16 = 0x12;
const EV_REP: u16 = 0x14;
const EV_FF: u16 = 0x15;
const EV_PWR: u16 = 0x16;
const EV_FF_STATUS: u16 = 0x17;
const EV_MAX: u16 = 0x1f;
const EV_CNT: u16 = EV_MAX + 1;
const KEY_RESERVED: u16 = 0;
const KEY_ESC: u16 = 1;
const KEY_1: u16 = 2;
const KEY_2: u16 = 3;
const KEY_3: u16 = 4;
const KEY_4: u16 = 5;
const KEY_5: u16 = 6;
const KEY_6: u16 = 7;
const KEY_7: u16 = 8;
const KEY_8: u16 = 9;
const KEY_9: u16 = 10;
const KEY_0: u16 = 11;
const KEY_MINUS: u16 = 12;
const KEY_EQUAL: u16 = 13;
const KEY_BACKSPACE: u16 = 14;
const KEY_TAB: u16 = 15;
const KEY_Q: u16 = 16;
const KEY_W: u16 = 17;
const KEY_E: u16 = 18;
const KEY_R: u16 = 19;
const KEY_T: u16 = 20;
const KEY_Y: u16 = 21;
const KEY_U: u16 = 22;
const KEY_I: u16 = 23;
const KEY_O: u16 = 24;
const KEY_P: u16 = 25;
const KEY_LEFTBRACE: u16 = 26;
const KEY_RIGHTBRACE: u16 = 27;
const KEY_ENTER: u16 = 28;
const KEY_LEFTCTRL: u16 = 29;
const KEY_A: u16 = 30;
const KEY_S: u16 = 31;
const KEY_D: u16 = 32;
const KEY_F: u16 = 33;
const KEY_G: u16 = 34;
const KEY_H: u16 = 35;
const KEY_J: u16 = 36;
const KEY_K: u16 = 37;
const KEY_L: u16 = 38;
const KEY_SEMICOLON: u16 = 39;
const KEY_APOSTROPHE: u16 = 40;
const KEY_GRAVE: u16 = 41;
const KEY_LEFTSHIFT: u16 = 42;
const KEY_BACKSLASH: u16 = 43;
const KEY_Z: u16 = 44;
const KEY_X: u16 = 45;
const KEY_C: u16 = 46;
const KEY_V: u16 = 47;
const KEY_B: u16 = 48;
const KEY_N: u16 = 49;
const KEY_M: u16 = 50;
const KEY_COMMA: u16 = 51;
const KEY_DOT: u16 = 52;
const KEY_SLASH: u16 = 53;
const KEY_RIGHTSHIFT: u16 = 54;
const KEY_KPASTERISK: u16 = 55;
const KEY_LEFTALT: u16 = 56;
const KEY_SPACE: u16 = 57;
const KEY_CAPSLOCK: u16 = 58;
const KEY_F1: u16 = 59;
const KEY_F2: u16 = 60;
const KEY_F3: u16 = 61;
const KEY_F4: u16 = 62;
const KEY_F5: u16 = 63;
const KEY_F6: u16 = 64;
const KEY_F7: u16 = 65;
const KEY_F8: u16 = 66;
const KEY_F9: u16 = 67;
const KEY_F10: u16 = 68;
const KEY_NUMLOCK: u16 = 69;
const KEY_SCROLLLOCK: u16 = 70;
const KEY_KP7: u16 = 71;
const KEY_KP8: u16 = 72;
const KEY_KP9: u16 = 73;
const KEY_KPMINUS: u16 = 74;
const KEY_KP4: u16 = 75;
const KEY_KP5: u16 = 76;
const KEY_KP6: u16 = 77;
const KEY_KPPLUS: u16 = 78;
const KEY_KP1: u16 = 79;
const KEY_KP2: u16 = 80;
const KEY_KP3: u16 = 81;
const KEY_KP0: u16 = 82;
const KEY_KPDOT: u16 = 83;
const KEY_ZENKAKUHANKAKU: u16 = 85;
const KEY_102ND: u16 = 86;
const KEY_F11: u16 = 87;
const KEY_F12: u16 = 88;
const KEY_RO: u16 = 89;
const KEY_KATAKANA: u16 = 90;
const KEY_HIRAGANA: u16 = 91;
const KEY_HENKAN: u16 = 92;
const KEY_KATAKANAHIRAGANA: u16 = 93;
const KEY_MUHENKAN: u16 = 94;
const KEY_KPJPCOMMA: u16 = 95;
const KEY_KPENTER: u16 = 96;
const KEY_RIGHTCTRL: u16 = 97;
const KEY_KPSLASH: u16 = 98;
const KEY_SYSRQ: u16 = 99;
const KEY_RIGHTALT: u16 = 100;
const KEY_LINEFEED: u16 = 101;
const KEY_HOME: u16 = 102;
const KEY_UP: u16 = 103;
const KEY_PAGEUP: u16 = 104;
const KEY_LEFT: u16 = 105;
const KEY_RIGHT: u16 = 106;
const KEY_END: u16 = 107;
const KEY_DOWN: u16 = 108;
const KEY_PAGEDOWN: u16 = 109;
const KEY_INSERT: u16 = 110;
const KEY_DELETE: u16 = 111;
const KEY_MACRO: u16 = 112;
const KEY_MUTE: u16 = 113;
const KEY_VOLUMEDOWN: u16 = 114;
const KEY_VOLUMEUP: u16 = 115;
const KEY_POWER: u16 = 116;
const KEY_KPEQUAL: u16 = 117;
const KEY_KPPLUSMINUS: u16 = 118;
const KEY_PAUSE: u16 = 119;
const KEY_SCALE: u16 = 120;
const KEY_KPCOMMA: u16 = 121;
const KEY_HANGEUL: u16 = 122;
const KEY_HANGUEL: u16 = KEY_HANGEUL;
const KEY_HANJA: u16 = 123;
const KEY_YEN: u16 = 124;
const KEY_LEFTMETA: u16 = 125;
const KEY_RIGHTMETA: u16 = 126;
const KEY_COMPOSE: u16 = 127;
const KEY_STOP: u16 = 128;
const KEY_AGAIN: u16 = 129;
const KEY_PROPS: u16 = 130;
const KEY_UNDO: u16 = 131;
const KEY_FRONT: u16 = 132;
const KEY_COPY: u16 = 133;
const KEY_OPEN: u16 = 134;
const KEY_PASTE: u16 = 135;
const KEY_FIND: u16 = 136;
const KEY_CUT: u16 = 137;
const KEY_HELP: u16 = 138;
const KEY_MENU: u16 = 139;
const KEY_CALC: u16 = 140;
const KEY_SETUP: u16 = 141;
const KEY_SLEEP: u16 = 142;
const KEY_WAKEUP: u16 = 143;
const KEY_FILE: u16 = 144;
const KEY_SENDFILE: u16 = 145;
const KEY_DELETEFILE: u16 = 146;
const KEY_XFER: u16 = 147;
const KEY_PROG1: u16 = 148;
const KEY_PROG2: u16 = 149;
const KEY_WWW: u16 = 150;
const KEY_MSDOS: u16 = 151;
const KEY_COFFEE: u16 = 152;
const KEY_SCREENLOCK: u16 = KEY_COFFEE;
const KEY_ROTATE_DISPLAY: u16 = 153;
const KEY_DIRECTION: u16 = KEY_ROTATE_DISPLAY;
const KEY_CYCLEWINDOWS: u16 = 154;
const KEY_MAIL: u16 = 155;
const KEY_BOOKMARKS: u16 = 156;
const KEY_COMPUTER: u16 = 157;
const KEY_BACK: u16 = 158;
const KEY_FORWARD: u16 = 159;
const KEY_CLOSECD: u16 = 160;
const KEY_EJECTCD: u16 = 161;
const KEY_EJECTCLOSECD: u16 = 162;
const KEY_NEXTSONG: u16 = 163;
const KEY_PLAYPAUSE: u16 = 164;
const KEY_PREVIOUSSONG: u16 = 165;
const KEY_STOPCD: u16 = 166;
const KEY_RECORD: u16 = 167;
const KEY_REWIND: u16 = 168;
const KEY_PHONE: u16 = 169;
const KEY_ISO: u16 = 170;
const KEY_CONFIG: u16 = 171;
const KEY_HOMEPAGE: u16 = 172;
const KEY_REFRESH: u16 = 173;
const KEY_EXIT: u16 = 174;
const KEY_MOVE: u16 = 175;
const KEY_EDIT: u16 = 176;
const KEY_SCROLLUP: u16 = 177;
const KEY_SCROLLDOWN: u16 = 178;
const KEY_KPLEFTPAREN: u16 = 179;
const KEY_KPRIGHTPAREN: u16 = 180;
const KEY_NEW: u16 = 181;
const KEY_REDO: u16 = 182;
const KEY_F13: u16 = 183;
const KEY_F14: u16 = 184;
const KEY_F15: u16 = 185;
const KEY_F16: u16 = 186;
const KEY_F17: u16 = 187;
const KEY_F18: u16 = 188;
const KEY_F19: u16 = 189;
const KEY_F20: u16 = 190;
const KEY_F21: u16 = 191;
const KEY_F22: u16 = 192;
const KEY_F23: u16 = 193;
const KEY_F24: u16 = 194;
const KEY_PLAYCD: u16 = 200;
const KEY_PAUSECD: u16 = 201;
const KEY_PROG3: u16 = 202;
const KEY_PROG4: u16 = 203;
const KEY_DASHBOARD: u16 = 204;
const KEY_SUSPEND: u16 = 205;
const KEY_CLOSE: u16 = 206;
const KEY_PLAY: u16 = 207;
const KEY_FASTFORWARD: u16 = 208;
const KEY_BASSBOOST: u16 = 209;
const KEY_PRINT: u16 = 210;
const KEY_HP: u16 = 211;
const KEY_CAMERA: u16 = 212;
const KEY_SOUND: u16 = 213;
const KEY_QUESTION: u16 = 214;
const KEY_EMAIL: u16 = 215;
const KEY_CHAT: u16 = 216;
const KEY_SEARCH: u16 = 217;
const KEY_CONNECT: u16 = 218;
const KEY_FINANCE: u16 = 219;
const KEY_SPORT: u16 = 220;
const KEY_SHOP: u16 = 221;
const KEY_ALTERASE: u16 = 222;
const KEY_CANCEL: u16 = 223;
const KEY_BRIGHTNESSDOWN: u16 = 224;
const KEY_BRIGHTNESSUP: u16 = 225;
const KEY_MEDIA: u16 = 226;
const KEY_SWITCHVIDEOMODE: u16 = 227;
const KEY_KBDILLUMTOGGLE: u16 = 228;
const KEY_KBDILLUMDOWN: u16 = 229;
const KEY_KBDILLUMUP: u16 = 230;
const KEY_SEND: u16 = 231;
const KEY_REPLY: u16 = 232;
const KEY_FORWARDMAIL: u16 = 233;
const KEY_SAVE: u16 = 234;
const KEY_DOCUMENTS: u16 = 235;
const KEY_BATTERY: u16 = 236;
const KEY_BLUETOOTH: u16 = 237;
const KEY_WLAN: u16 = 238;
const KEY_UWB: u16 = 239;
const KEY_UNKNOWN: u16 = 240;
const KEY_VIDEO_NEXT: u16 = 241;
const KEY_VIDEO_PREV: u16 = 242;
const KEY_BRIGHTNESS_CYCLE: u16 = 243;
const KEY_BRIGHTNESS_AUTO: u16 = 244;
const KEY_BRIGHTNESS_ZERO: u16 = KEY_BRIGHTNESS_AUTO;
const KEY_DISPLAY_OFF: u16 = 245;
const KEY_WWAN: u16 = 246;
const KEY_WIMAX: u16 = KEY_WWAN;
const KEY_RFKILL: u16 = 247;
const KEY_MICMUTE: u16 = 248;
const BTN_MISC: u16 = 0x100;
const BTN_0: u16 = 0x100;
const BTN_1: u16 = 0x101;
const BTN_2: u16 = 0x102;
const BTN_3: u16 = 0x103;
const BTN_4: u16 = 0x104;
const BTN_5: u16 = 0x105;
const BTN_6: u16 = 0x106;
const BTN_7: u16 = 0x107;
const BTN_8: u16 = 0x108;
const BTN_9: u16 = 0x109;
const BTN_MOUSE: u16 = 0x110;
const BTN_LEFT: u16 = 0x110;
const BTN_RIGHT: u16 = 0x111;
const BTN_MIDDLE: u16 = 0x112;
const BTN_SIDE: u16 = 0x113;
const BTN_EXTRA: u16 = 0x114;
const BTN_FORWARD: u16 = 0x115;
const BTN_BACK: u16 = 0x116;
const BTN_TASK: u16 = 0x117;
const BTN_JOYSTICK: u16 = 0x120;
const BTN_TRIGGER: u16 = 0x120;
const BTN_THUMB: u16 = 0x121;
const BTN_THUMB2: u16 = 0x122;
const BTN_TOP: u16 = 0x123;
const BTN_TOP2: u16 = 0x124;
const BTN_PINKIE: u16 = 0x125;
const BTN_BASE: u16 = 0x126;
const BTN_BASE2: u16 = 0x127;
const BTN_BASE3: u16 = 0x128;
const BTN_BASE4: u16 = 0x129;
const BTN_BASE5: u16 = 0x12a;
const BTN_BASE6: u16 = 0x12b;
const BTN_DEAD: u16 = 0x12f;
const BTN_GAMEPAD: u16 = 0x130;
const BTN_SOUTH: u16 = 0x130;
const BTN_A: u16 = BTN_SOUTH;
const BTN_EAST: u16 = 0x131;
const BTN_B: u16 = BTN_EAST;
const BTN_C: u16 = 0x132;
const BTN_NORTH: u16 = 0x133;
const BTN_X: u16 = BTN_NORTH;
const BTN_WEST: u16 = 0x134;
const BTN_Y: u16 = BTN_WEST;
const BTN_Z: u16 = 0x135;
const BTN_TL: u16 = 0x136;
const BTN_TR: u16 = 0x137;
const BTN_TL2: u16 = 0x138;
const BTN_TR2: u16 = 0x139;
const BTN_SELECT: u16 = 0x13a;
const BTN_START: u16 = 0x13b;
const BTN_MODE: u16 = 0x13c;
const BTN_THUMBL: u16 = 0x13d;
const BTN_THUMBR: u16 = 0x13e;
const BTN_DIGI: u16 = 0x140;
const BTN_TOOL_PEN: u16 = 0x140;
const BTN_TOOL_RUBBER: u16 = 0x141;
const BTN_TOOL_BRUSH: u16 = 0x142;
const BTN_TOOL_PENCIL: u16 = 0x143;
const BTN_TOOL_AIRBRUSH: u16 = 0x144;
const BTN_TOOL_FINGER: u16 = 0x145;
const BTN_TOOL_MOUSE: u16 = 0x146;
const BTN_TOOL_LENS: u16 = 0x147;
const BTN_TOOL_QUINTTAP: u16 = 0x148;
const BTN_TOUCH: u16 = 0x14a;
const BTN_STYLUS: u16 = 0x14b;
const BTN_STYLUS2: u16 = 0x14c;
const BTN_TOOL_DOUBLETAP: u16 = 0x14d;
const BTN_TOOL_TRIPLETAP: u16 = 0x14e;
const BTN_TOOL_QUADTAP: u16 = 0x14f;
const BTN_WHEEL: u16 = 0x150;
const BTN_GEAR_DOWN: u16 = 0x150;
const BTN_GEAR_UP: u16 = 0x151;
const KEY_OK: u16 = 0x160;
const KEY_SELECT: u16 = 0x161;
const KEY_GOTO: u16 = 0x162;
const KEY_CLEAR: u16 = 0x163;
const KEY_POWER2: u16 = 0x164;
const KEY_OPTION: u16 = 0x165;
const KEY_INFO: u16 = 0x166;
const KEY_TIME: u16 = 0x167;
const KEY_VENDOR: u16 = 0x168;
const KEY_ARCHIVE: u16 = 0x169;
const KEY_PROGRAM: u16 = 0x16a;
const KEY_CHANNEL: u16 = 0x16b;
const KEY_FAVORITES: u16 = 0x16c;
const KEY_EPG: u16 = 0x16d;
const KEY_PVR: u16 = 0x16e;
const KEY_MHP: u16 = 0x16f;
const KEY_LANGUAGE: u16 = 0x170;
const KEY_TITLE: u16 = 0x171;
const KEY_SUBTITLE: u16 = 0x172;
const KEY_ANGLE: u16 = 0x173;
const KEY_ZOOM: u16 = 0x174;
const KEY_MODE: u16 = 0x175;
const KEY_KEYBOARD: u16 = 0x176;
const KEY_SCREEN: u16 = 0x177;
const KEY_PC: u16 = 0x178;
const KEY_TV: u16 = 0x179;
const KEY_TV2: u16 = 0x17a;
const KEY_VCR: u16 = 0x17b;
const KEY_VCR2: u16 = 0x17c;
const KEY_SAT: u16 = 0x17d;
const KEY_SAT2: u16 = 0x17e;
const KEY_CD: u16 = 0x17f;
const KEY_TAPE: u16 = 0x180;
const KEY_RADIO: u16 = 0x181;
const KEY_TUNER: u16 = 0x182;
const KEY_PLAYER: u16 = 0x183;
const KEY_TEXT: u16 = 0x184;
const KEY_DVD: u16 = 0x185;
const KEY_AUX: u16 = 0x186;
const KEY_MP3: u16 = 0x187;
const KEY_AUDIO: u16 = 0x188;
const KEY_VIDEO: u16 = 0x189;
const KEY_DIRECTORY: u16 = 0x18a;
const KEY_LIST: u16 = 0x18b;
const KEY_MEMO: u16 = 0x18c;
const KEY_CALENDAR: u16 = 0x18d;
const KEY_RED: u16 = 0x18e;
const KEY_GREEN: u16 = 0x18f;
const KEY_YELLOW: u16 = 0x190;
const KEY_BLUE: u16 = 0x191;
const KEY_CHANNELUP: u16 = 0x192;
const KEY_CHANNELDOWN: u16 = 0x193;
const KEY_FIRST: u16 = 0x194;
const KEY_LAST: u16 = 0x195;
const KEY_AB: u16 = 0x196;
const KEY_NEXT: u16 = 0x197;
const KEY_RESTART: u16 = 0x198;
const KEY_SLOW: u16 = 0x199;
const KEY_SHUFFLE: u16 = 0x19a;
const KEY_BREAK: u16 = 0x19b;
const KEY_PREVIOUS: u16 = 0x19c;
const KEY_DIGITS: u16 = 0x19d;
const KEY_TEEN: u16 = 0x19e;
const KEY_TWEN: u16 = 0x19f;
const KEY_VIDEOPHONE: u16 = 0x1a0;
const KEY_GAMES: u16 = 0x1a1;
const KEY_ZOOMIN: u16 = 0x1a2;
const KEY_ZOOMOUT: u16 = 0x1a3;
const KEY_ZOOMRESET: u16 = 0x1a4;
const KEY_WORDPROCESSOR: u16 = 0x1a5;
const KEY_EDITOR: u16 = 0x1a6;
const KEY_SPREADSHEET: u16 = 0x1a7;
const KEY_GRAPHICSEDITOR: u16 = 0x1a8;
const KEY_PRESENTATION: u16 = 0x1a9;
const KEY_DATABASE: u16 = 0x1aa;
const KEY_NEWS: u16 = 0x1ab;
const KEY_VOICEMAIL: u16 = 0x1ac;
const KEY_ADDRESSBOOK: u16 = 0x1ad;
const KEY_MESSENGER: u16 = 0x1ae;
const KEY_DISPLAYTOGGLE: u16 = 0x1af;
const KEY_BRIGHTNESS_TOGGLE: u16 = KEY_DISPLAYTOGGLE;
const KEY_SPELLCHECK: u16 = 0x1b0;
const KEY_LOGOFF: u16 = 0x1b1;
const KEY_DOLLAR: u16 = 0x1b2;
const KEY_EURO: u16 = 0x1b3;
const KEY_FRAMEBACK: u16 = 0x1b4;
const KEY_FRAMEFORWARD: u16 = 0x1b5;
const KEY_CONTEXT_MENU: u16 = 0x1b6;
const KEY_MEDIA_REPEAT: u16 = 0x1b7;
const KEY_10CHANNELSUP: u16 = 0x1b8;
const KEY_10CHANNELSDOWN: u16 = 0x1b9;
const KEY_IMAGES: u16 = 0x1ba;
const KEY_DEL_EOL: u16 = 0x1c0;
const KEY_DEL_EOS: u16 = 0x1c1;
const KEY_INS_LINE: u16 = 0x1c2;
const KEY_DEL_LINE: u16 = 0x1c3;
const KEY_FN: u16 = 0x1d0;
const KEY_FN_ESC: u16 = 0x1d1;
const KEY_FN_F1: u16 = 0x1d2;
const KEY_FN_F2: u16 = 0x1d3;
const KEY_FN_F3: u16 = 0x1d4;
const KEY_FN_F4: u16 = 0x1d5;
const KEY_FN_F5: u16 = 0x1d6;
const KEY_FN_F6: u16 = 0x1d7;
const KEY_FN_F7: u16 = 0x1d8;
const KEY_FN_F8: u16 = 0x1d9;
const KEY_FN_F9: u16 = 0x1da;
const KEY_FN_F10: u16 = 0x1db;
const KEY_FN_F11: u16 = 0x1dc;
const KEY_FN_F12: u16 = 0x1dd;
const KEY_FN_1: u16 = 0x1de;
const KEY_FN_2: u16 = 0x1df;
const KEY_FN_D: u16 = 0x1e0;
const KEY_FN_E: u16 = 0x1e1;
const KEY_FN_F: u16 = 0x1e2;
const KEY_FN_S: u16 = 0x1e3;
const KEY_FN_B: u16 = 0x1e4;
const KEY_BRL_DOT1: u16 = 0x1f1;
const KEY_BRL_DOT2: u16 = 0x1f2;
const KEY_BRL_DOT3: u16 = 0x1f3;
const KEY_BRL_DOT4: u16 = 0x1f4;
const KEY_BRL_DOT5: u16 = 0x1f5;
const KEY_BRL_DOT6: u16 = 0x1f6;
const KEY_BRL_DOT7: u16 = 0x1f7;
const KEY_BRL_DOT8: u16 = 0x1f8;
const KEY_BRL_DOT9: u16 = 0x1f9;
const KEY_BRL_DOT10: u16 = 0x1fa;
const KEY_NUMERIC_0: u16 = 0x200;
const KEY_NUMERIC_1: u16 = 0x201;
const KEY_NUMERIC_2: u16 = 0x202;
const KEY_NUMERIC_3: u16 = 0x203;
const KEY_NUMERIC_4: u16 = 0x204;
const KEY_NUMERIC_5: u16 = 0x205;
const KEY_NUMERIC_6: u16 = 0x206;
const KEY_NUMERIC_7: u16 = 0x207;
const KEY_NUMERIC_8: u16 = 0x208;
const KEY_NUMERIC_9: u16 = 0x209;
const KEY_NUMERIC_STAR: u16 = 0x20a;
const KEY_NUMERIC_POUND: u16 = 0x20b;
const KEY_NUMERIC_A: u16 = 0x20c;
const KEY_NUMERIC_B: u16 = 0x20d;
const KEY_NUMERIC_C: u16 = 0x20e;
const KEY_NUMERIC_D: u16 = 0x20f;
const KEY_CAMERA_FOCUS: u16 = 0x210;
const KEY_WPS_BUTTON: u16 = 0x211;
const KEY_TOUCHPAD_TOGGLE: u16 = 0x212;
const KEY_TOUCHPAD_ON: u16 = 0x213;
const KEY_TOUCHPAD_OFF: u16 = 0x214;
const KEY_CAMERA_ZOOMIN: u16 = 0x215;
const KEY_CAMERA_ZOOMOUT: u16 = 0x216;
const KEY_CAMERA_UP: u16 = 0x217;
const KEY_CAMERA_DOWN: u16 = 0x218;
const KEY_CAMERA_LEFT: u16 = 0x219;
const KEY_CAMERA_RIGHT: u16 = 0x21a;
const KEY_ATTENDANT_ON: u16 = 0x21b;
const KEY_ATTENDANT_OFF: u16 = 0x21c;
const KEY_ATTENDANT_TOGGLE: u16 = 0x21d;
const KEY_LIGHTS_TOGGLE: u16 = 0x21e;
const BTN_DPAD_UP: u16 = 0x220;
const BTN_DPAD_DOWN: u16 = 0x221;
const BTN_DPAD_LEFT: u16 = 0x222;
const BTN_DPAD_RIGHT: u16 = 0x223;
const KEY_ALS_TOGGLE: u16 = 0x230;
const KEY_BUTTONCONFIG: u16 = 0x240;
const KEY_TASKMANAGER: u16 = 0x241;
const KEY_JOURNAL: u16 = 0x242;
const KEY_CONTROLPANEL: u16 = 0x243;
const KEY_APPSELECT: u16 = 0x244;
const KEY_SCREENSAVER: u16 = 0x245;
const KEY_VOICECOMMAND: u16 = 0x246;
const KEY_BRIGHTNESS_MIN: u16 = 0x250;
const KEY_BRIGHTNESS_MAX: u16 = 0x251;
const KEY_KBDINPUTASSIST_PREV: u16 = 0x260;
const KEY_KBDINPUTASSIST_NEXT: u16 = 0x261;
const KEY_KBDINPUTASSIST_PREVGROUP: u16 = 0x262;
const KEY_KBDINPUTASSIST_NEXTGROUP: u16 = 0x263;
const KEY_KBDINPUTASSIST_ACCEPT: u16 = 0x264;
const KEY_KBDINPUTASSIST_CANCEL: u16 = 0x265;
const KEY_RIGHT_UP: u16 = 0x266;
const KEY_RIGHT_DOWN: u16 = 0x267;
const KEY_LEFT_UP: u16 = 0x268;
const KEY_LEFT_DOWN: u16 = 0x269;
const KEY_ROOT_MENU: u16 = 0x26a;
const KEY_MEDIA_TOP_MENU: u16 = 0x26b;
const KEY_NUMERIC_11: u16 = 0x26c;
const KEY_NUMERIC_12: u16 = 0x26d;
const KEY_AUDIO_DESC: u16 = 0x26e;
const KEY_3D_MODE: u16 = 0x26f;
const KEY_NEXT_FAVORITE: u16 = 0x270;
const KEY_STOP_RECORD: u16 = 0x271;
const KEY_PAUSE_RECORD: u16 = 0x272;
const KEY_VOD: u16 = 0x273;
const KEY_UNMUTE: u16 = 0x274;
const KEY_FASTREVERSE: u16 = 0x275;
const KEY_SLOWREVERSE: u16 = 0x276;
const KEY_DATA: u16 = 0x277;
const BTN_TRIGGER_HAPPY: u16 = 0x2c0;
const BTN_TRIGGER_HAPPY1: u16 = 0x2c0;
const BTN_TRIGGER_HAPPY2: u16 = 0x2c1;
const BTN_TRIGGER_HAPPY3: u16 = 0x2c2;
const BTN_TRIGGER_HAPPY4: u16 = 0x2c3;
const BTN_TRIGGER_HAPPY5: u16 = 0x2c4;
const BTN_TRIGGER_HAPPY6: u16 = 0x2c5;
const BTN_TRIGGER_HAPPY7: u16 = 0x2c6;
const BTN_TRIGGER_HAPPY8: u16 = 0x2c7;
const BTN_TRIGGER_HAPPY9: u16 = 0x2c8;
const BTN_TRIGGER_HAPPY10: u16 = 0x2c9;
const BTN_TRIGGER_HAPPY11: u16 = 0x2ca;
const BTN_TRIGGER_HAPPY12: u16 = 0x2cb;
const BTN_TRIGGER_HAPPY13: u16 = 0x2cc;
const BTN_TRIGGER_HAPPY14: u16 = 0x2cd;
const BTN_TRIGGER_HAPPY15: u16 = 0x2ce;
const BTN_TRIGGER_HAPPY16: u16 = 0x2cf;
const BTN_TRIGGER_HAPPY17: u16 = 0x2d0;
const BTN_TRIGGER_HAPPY18: u16 = 0x2d1;
const BTN_TRIGGER_HAPPY19: u16 = 0x2d2;
const BTN_TRIGGER_HAPPY20: u16 = 0x2d3;
const BTN_TRIGGER_HAPPY21: u16 = 0x2d4;
const BTN_TRIGGER_HAPPY22: u16 = 0x2d5;
const BTN_TRIGGER_HAPPY23: u16 = 0x2d6;
const BTN_TRIGGER_HAPPY24: u16 = 0x2d7;
const BTN_TRIGGER_HAPPY25: u16 = 0x2d8;
const BTN_TRIGGER_HAPPY26: u16 = 0x2d9;
const BTN_TRIGGER_HAPPY27: u16 = 0x2da;
const BTN_TRIGGER_HAPPY28: u16 = 0x2db;
const BTN_TRIGGER_HAPPY29: u16 = 0x2dc;
const BTN_TRIGGER_HAPPY30: u16 = 0x2dd;
const BTN_TRIGGER_HAPPY31: u16 = 0x2de;
const BTN_TRIGGER_HAPPY32: u16 = 0x2df;
const BTN_TRIGGER_HAPPY33: u16 = 0x2e0;
const BTN_TRIGGER_HAPPY34: u16 = 0x2e1;
const BTN_TRIGGER_HAPPY35: u16 = 0x2e2;
const BTN_TRIGGER_HAPPY36: u16 = 0x2e3;
const BTN_TRIGGER_HAPPY37: u16 = 0x2e4;
const BTN_TRIGGER_HAPPY38: u16 = 0x2e5;
const BTN_TRIGGER_HAPPY39: u16 = 0x2e6;
const BTN_TRIGGER_HAPPY40: u16 = 0x2e7;
const REL_X: u16 = 0x00;
const REL_Y: u16 = 0x01;
const REL_Z: u16 = 0x02;
const REL_RX: u16 = 0x03;
const REL_RY: u16 = 0x04;
const REL_RZ: u16 = 0x05;
const REL_HWHEEL: u16 = 0x06;
const REL_DIAL: u16 = 0x07;
const REL_WHEEL: u16 = 0x08;
const REL_MISC: u16 = 0x09;
const REL_RESERVED: u16 = 0x0a;
const REL_WHEEL_HI_RES: u16 = 0x0b;
const REL_HWHEEL_HI_RES: u16 = 0x0c;
const REL_MAX: u16 = 0x0f;
const REL_CNT: u16 = REL_MAX + 1;
impl From<u16> for ButtonId {
fn from(val: u16) -> Self {
match val {
0x100..=0x109 => ButtonId((val - 0x100) as u32),
_ => ButtonId(0),
}
}
}
impl From<i32> for ElementState {
fn from(val: i32) -> Self {
match val {
0 => Self::Released,
1 => Self::Pressed,
2 => Self::Repeated,
_ => Self::Unknown,
}
}
}
impl From<RawEvent> for Event {
fn from(val: RawEvent) -> Self {
match val.type_() {
EV_KEY => match val.code() {
0..=255 => Event::Key(KeyboardInput {
scancode: val.code() as u32,
state: val.value().into(),
virtual_keycode: val.code().try_into().ok(),
}),
0x100..=0x109 => Event::Button {
button: val.code().into(),
state: val.value().into(),
},
0x110 => Event::MouseButton {
button: MouseButton::Left,
state: val.value().into(),
},
0x111 => Event::MouseButton {
button: MouseButton::Right,
state: val.value().into(),
},
0x112 => Event::MouseButton {
button: MouseButton::Middle,
state: val.value().into(),
},
_ => Event::Key(KeyboardInput::default()),
},
EV_REL => match val.code() {
REL_X => Event::MouseMotion {
delta: (val.value() as i32 as f64, 0.0),
},
REL_Y => Event::MouseMotion {
delta: (0.0, val.value() as i32 as f64),
},
REL_WHEEL | REL_WHEEL_HI_RES => Event::MouseWheel {
delta: MouseScrollDelta::LineDelta(0.0, val.value() as i32 as f32),
},
REL_HWHEEL | REL_HWHEEL_HI_RES => Event::MouseWheel {
delta: MouseScrollDelta::LineDelta(val.value() as i32 as f32, 0.0),
},
_ => Event::Dummy,
},
_ => Event::Dummy,
}
}
}
impl TryFrom<u16> for VirtualKeyCode {
type Error = &'static str;
fn try_from(val: u16) -> Result<Self, Self::Error> {
match val {
KEY_ESC => Ok(VirtualKeyCode::Escape),
KEY_1 => Ok(VirtualKeyCode::Key1),
KEY_2 => Ok(VirtualKeyCode::Key2),
KEY_3 => Ok(VirtualKeyCode::Key3),
KEY_4 => Ok(VirtualKeyCode::Key4),
KEY_5 => Ok(VirtualKeyCode::Key5),
KEY_6 => Ok(VirtualKeyCode::Key6),
KEY_7 => Ok(VirtualKeyCode::Key7),
KEY_8 => Ok(VirtualKeyCode::Key8),
KEY_9 => Ok(VirtualKeyCode::Key9),
KEY_0 => Ok(VirtualKeyCode::Key0),
KEY_MINUS => Ok(VirtualKeyCode::Minus),
KEY_EQUAL => Ok(VirtualKeyCode::Equals),
KEY_BACKSPACE => Ok(VirtualKeyCode::Back),
KEY_TAB => Ok(VirtualKeyCode::Tab),
KEY_Q => Ok(VirtualKeyCode::Q),
KEY_W => Ok(VirtualKeyCode::W),
KEY_E => Ok(VirtualKeyCode::E),
KEY_R => Ok(VirtualKeyCode::R),
KEY_T => Ok(VirtualKeyCode::T),
KEY_Y => Ok(VirtualKeyCode::Y),
KEY_U => Ok(VirtualKeyCode::U),
KEY_I => Ok(VirtualKeyCode::I),
KEY_O => Ok(VirtualKeyCode::O),
KEY_P => Ok(VirtualKeyCode::P),
KEY_LEFTBRACE => Ok(VirtualKeyCode::LBracket),
KEY_RIGHTBRACE => Ok(VirtualKeyCode::RBracket),
KEY_ENTER => Ok(VirtualKeyCode::Return),
KEY_LEFTCTRL => Ok(VirtualKeyCode::LControl),
KEY_A => Ok(VirtualKeyCode::A),
KEY_S => Ok(VirtualKeyCode::S),
KEY_D => Ok(VirtualKeyCode::D),
KEY_F => Ok(VirtualKeyCode::F),
KEY_G => Ok(VirtualKeyCode::G),
KEY_H => Ok(VirtualKeyCode::H),
KEY_J => Ok(VirtualKeyCode::J),
KEY_K => Ok(VirtualKeyCode::K),
KEY_L => Ok(VirtualKeyCode::L),
KEY_SEMICOLON => Ok(VirtualKeyCode::Semicolon),
KEY_APOSTROPHE => Ok(VirtualKeyCode::Apostrophe),
KEY_GRAVE => Ok(VirtualKeyCode::Grave),
KEY_LEFTSHIFT => Ok(VirtualKeyCode::LShift),
KEY_BACKSLASH => Ok(VirtualKeyCode::Backslash),
KEY_Z => Ok(VirtualKeyCode::Z),
KEY_X => Ok(VirtualKeyCode::X),
KEY_C => Ok(VirtualKeyCode::C),
KEY_V => Ok(VirtualKeyCode::V),
KEY_B => Ok(VirtualKeyCode::B),
KEY_N => Ok(VirtualKeyCode::N),
KEY_M => Ok(VirtualKeyCode::M),
KEY_COMMA => Ok(VirtualKeyCode::Comma),
KEY_DOT => Ok(VirtualKeyCode::Period),
KEY_SLASH => Ok(VirtualKeyCode::Slash),
KEY_RIGHTSHIFT => Ok(VirtualKeyCode::RShift),
KEY_LEFTALT => Ok(VirtualKeyCode::LAlt),
KEY_SPACE => Ok(VirtualKeyCode::Space),
KEY_CAPSLOCK => Ok(VirtualKeyCode::Capital),
KEY_F1 => Ok(VirtualKeyCode::F1),
KEY_F2 => Ok(VirtualKeyCode::F2),
KEY_F3 => Ok(VirtualKeyCode::F3),
KEY_F4 => Ok(VirtualKeyCode::F4),
KEY_F5 => Ok(VirtualKeyCode::F5),
KEY_F6 => Ok(VirtualKeyCode::F6),
KEY_F7 => Ok(VirtualKeyCode::F7),
KEY_F8 => Ok(VirtualKeyCode::F8),
KEY_F9 => Ok(VirtualKeyCode::F9),
KEY_F10 => Ok(VirtualKeyCode::F10),
KEY_NUMLOCK => Ok(VirtualKeyCode::Numlock),
KEY_SCROLLLOCK => Ok(VirtualKeyCode::Scroll),
KEY_KP7 => Ok(VirtualKeyCode::Numpad7),
KEY_KP8 => Ok(VirtualKeyCode::Numpad8),
KEY_KP9 => Ok(VirtualKeyCode::Numpad9),
KEY_KPMINUS => Ok(VirtualKeyCode::Minus),
KEY_KP4 => Ok(VirtualKeyCode::Numpad4),
KEY_KP5 => Ok(VirtualKeyCode::Numpad5),
KEY_KP6 => Ok(VirtualKeyCode::Numpad6),
KEY_KPPLUS => Ok(VirtualKeyCode::Plus),
KEY_KP1 => Ok(VirtualKeyCode::Numpad1),
KEY_KP2 => Ok(VirtualKeyCode::Numpad2),
KEY_KP3 => Ok(VirtualKeyCode::Numpad3),
KEY_KP0 => Ok(VirtualKeyCode::Numpad0),
KEY_F11 => Ok(VirtualKeyCode::F11),
KEY_F12 => Ok(VirtualKeyCode::F12),
KEY_RIGHTCTRL => Ok(VirtualKeyCode::RControl),
KEY_SYSRQ => Ok(VirtualKeyCode::Sysrq),
KEY_RIGHTALT => Ok(VirtualKeyCode::RAlt),
KEY_HOME => Ok(VirtualKeyCode::Home),
KEY_UP => Ok(VirtualKeyCode::Up),
KEY_PAGEUP => Ok(VirtualKeyCode::PageUp),
KEY_LEFT => Ok(VirtualKeyCode::Left),
KEY_RIGHT => Ok(VirtualKeyCode::Right),
KEY_END => Ok(VirtualKeyCode::End),
KEY_DOWN => Ok(VirtualKeyCode::Down),
KEY_PAGEDOWN => Ok(VirtualKeyCode::PageDown),
KEY_INSERT => Ok(VirtualKeyCode::Insert),
KEY_DELETE => Ok(VirtualKeyCode::Delete),
KEY_POWER => Ok(VirtualKeyCode::Power),
KEY_PAUSE => Ok(VirtualKeyCode::Pause),
_ => Err("Unsupported!"),
}
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId(usize);
impl Display for DeviceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl FromStr for DeviceId {
type Err = &'static str;
fn from_str(val: &str) -> Result<Self, Self::Err> {
let seg = val.strip_prefix("event").ok_or("Not an event device!")?;
let nth = seg
.parse::<usize>()
.map_err(|_| "Not a numbered event device!")?;
Ok(DeviceId(nth))
}
}
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct RawEvent {
inner: input_event,
}
impl Default for RawEvent {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
impl Debug for RawEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RawEvent")
.field("time", &TimeVal::from(self.inner.time))
.field("type", &self.inner.type_)
.field("code", &self.inner.code)
.field("value", &self.inner.value)
.finish()
}
}
impl Display for RawEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"RawEvent {{ time: {}, type: {}, code: {}, value: {} }}",
TimeVal::from(self.inner.time),
self.inner.type_,
self.inner.code,
self.inner.value
)
}
}
impl RawEvent {
pub fn time(&self) -> TimeVal {
TimeVal::from(self.inner.time)
}
pub fn type_(&self) -> u16 {
self.inner.type_
}
pub fn code(&self) -> u16 {
self.inner.code
}
pub fn value(&self) -> i32 {
self.inner.value
}
pub fn is_sync(&self) -> bool {
self.type_() == 0 && self.code() == 0 && self.value() == 0
}
}
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct TimeVal {
inner: timeval,
}
impl From<timeval> for TimeVal {
fn from(val: timeval) -> Self {
Self { inner: val }
}
}
impl Into<timeval> for TimeVal {
fn into(self) -> timeval {
self.inner
}
}
impl Into<(u32, u32)> for TimeVal {
fn into(self) -> (u32, u32) {
(self.inner.tv_sec as u32, self.inner.tv_usec as u32)
}
}
impl Into<u64> for TimeVal {
fn into(self) -> u64 {
self.inner.tv_sec as u64 * 1_000_000u64 + self.inner.tv_usec as u64
}
}
impl std::fmt::Debug for TimeVal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TimeVal")
.field("sec", &self.inner.tv_sec)
.field("usec", &self.inner.tv_usec)
.finish()
}
}
impl std::fmt::Display for TimeVal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}.{number:>0width$}",
self.inner.tv_sec,
number = self.inner.tv_usec,
width = 6
)
}
}
pub struct DeviceMeta {}
pub struct Device {
file: File,
id: DeviceId,
}
impl AsRawFd for Device {
fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
}
}
impl Debug for Device {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Device {{ id = {} }}", self.id())
}
}
impl Device {
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, std::io::Error> {
let file = File::open(&path)?;
let mut id = DeviceId::default();
if let Some(name) = path.as_ref().file_name() {
id = DeviceId::from_str(name.to_str().unwrap_or("")).unwrap_or_default();
}
Ok(Self { file, id })
}
pub fn set_non_blocking(&mut self, non_block: bool) {
unsafe {
let fd = self.file.as_raw_fd();
let mut flags = libc::fcntl(fd, libc::F_GETFL, 0);
if non_block {
flags |= libc::O_NONBLOCK;
} else {
flags &= !libc::O_NONBLOCK;
}
libc::fcntl(fd, libc::F_SETFL, flags);
}
}
pub fn events(&mut self) -> Events<'_> {
Events::new(self)
}
pub fn id(&self) -> DeviceId {
self.id
}
pub fn meta(&mut self) -> DeviceMeta {
DeviceMeta {}
}
pub fn raw_events(&mut self) -> RawEvents<'_> {
RawEvents::new(self)
}
pub fn raw_events_no_sync(&mut self) -> RawEventsNoSync {
RawEventsNoSync::new(self)
}
pub fn read_one(&mut self) -> Result<RawEvent, std::io::Error> {
const N: usize = std::mem::size_of::<RawEvent>();
let mut ev: RawEvent = Default::default();
let buf = unsafe { &mut *(&mut ev as *mut RawEvent as *mut [u8; N]) };
self.file.read_exact(buf)?;
Ok(ev)
}
}
pub struct Events<'a> {
raw_events: RawEventsNoSync<'a>,
}
impl<'a> Iterator for Events<'a> {
type Item = Event;
fn next(&mut self) -> Option<Self::Item> {
self.raw_events.next().map(|x| x.into())
}
}
impl<'a> Events<'a> {
pub fn new(dev: &'a mut Device) -> Self {
Self {
raw_events: dev.raw_events_no_sync(),
}
}
}
pub struct RawEvents<'a> {
dev: &'a mut Device,
}
impl<'a> Iterator for RawEvents<'a> {
type Item = RawEvent;
fn next(&mut self) -> Option<Self::Item> {
match self.dev.read_one() {
Ok(ev) => Some(ev),
Err(err) => match err.kind() {
ErrorKind::WouldBlock => None,
_ => unreachable!(),
},
}
}
}
impl<'a> RawEvents<'a> {
pub fn new(dev: &'a mut Device) -> Self {
Self { dev }
}
}
pub struct RawEventsNoSync<'a> {
raw_events: RawEvents<'a>,
}
impl<'a> Iterator for RawEventsNoSync<'a> {
type Item = RawEvent;
fn next(&mut self) -> Option<Self::Item> {
while let Some(ev) = self.raw_events.next() {
if ev.type_() != EV_SYN {
return Some(ev);
}
}
None
}
}
impl<'a> RawEventsNoSync<'a> {
pub fn new(dev: &'a mut Device) -> Self {
Self {
raw_events: dev.raw_events(),
}
}
}
pub fn enumerate() -> Vec<Device> {
let mut devices = Vec::new();
if let Ok(dir) = fs::read_dir("/dev/input") {
for entry in dir {
if let Ok(entry) = entry {
let path = entry.path();
if !path.is_dir() {
if let Some(name) = path.file_name() {
if !name.to_str().unwrap_or("").starts_with("event") {
continue;
}
}
if let Ok(dev) = Device::open(path) {
devices.push(dev);
}
}
}
}
}
devices
}
pub fn enumerate_shareable() -> Vec<Arc<Mutex<Device>>> {
enumerate()
.into_iter()
.map(|x| Arc::new(Mutex::new(x)))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_device() {
let mut dev = Device::open("/dev/input/event2").unwrap();
dev.set_non_blocking(true);
match dev.read_one() {
Ok(_ev) => {}
Err(err) => match err.kind() {
ErrorKind::WouldBlock => {}
_ => {}
},
}
}
}