dbus deamon wip

This commit is contained in:
Robin Appelman 2020-04-10 22:09:29 +02:00
commit 107c21b6a5
5 changed files with 851 additions and 559 deletions

100
Cargo.lock generated
View file

@ -1,5 +1,14 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.0.0" version = "1.0.0"
@ -24,6 +33,16 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "dbus"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f8875bb7afbc20dec12db09e18af3dcbd672b08592d2932950326a6437c616"
dependencies = [
"libc",
"libdbus-sys",
]
[[package]] [[package]]
name = "derivative" name = "derivative"
version = "2.1.0" version = "2.1.0"
@ -60,18 +79,39 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.68" version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
[[package]]
name = "libdbus-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc12a3bc971424edbbf7edaf6e5740483444db63aa8e23d3751ff12a30f306f0"
dependencies = [
"pkg-config",
]
[[package]] [[package]]
name = "main_error" name = "main_error"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3516df0fb44d98fe6d6e859d224adfb7b6686447937e5b96308d6061595eed04" checksum = "3516df0fb44d98fe6d6e859d224adfb7b6686447937e5b96308d6061595eed04"
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.8.1" version = "0.8.1"
@ -184,6 +224,37 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "parse-display"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718b422bc6b056b6374f7ffc3b2d9b55180a4af59a089835df1963994676d8b6"
dependencies = [
"lazy_static",
"parse-display-derive",
"regex",
]
[[package]]
name = "parse-display-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7cf2deb364a60cc0f633c1ffe619b42463993c91352ae367010b8420e442655"
dependencies = [
"lazy_static",
"proc-macro2",
"quote",
"regex",
"regex-syntax",
"syn",
]
[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "0.1.4" version = "0.1.4"
@ -248,6 +319,24 @@ dependencies = [
"rand_core 0.3.1", "rand_core 0.3.1",
] ]
[[package]]
name = "regex"
version = "1.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
[[package]] [[package]]
name = "rustc-serialize" name = "rustc-serialize"
version = "0.3.24" version = "0.3.24"
@ -264,9 +353,11 @@ checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
name = "shortcutd" name = "shortcutd"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"dbus",
"evdev", "evdev",
"main_error", "main_error",
"num_enum", "num_enum",
"parse-display",
] ]
[[package]] [[package]]
@ -280,6 +371,15 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.6" version = "0.5.6"

View file

@ -8,3 +8,5 @@ edition = "2018"
evdev = "0.10.1" evdev = "0.10.1"
main_error = "0.1.0" main_error = "0.1.0"
num_enum = "0.4.3" num_enum = "0.4.3"
dbus = "0.8.2"
parse-display = "0.1.1"

View file

@ -1,6 +1,7 @@
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
use parse_display::{Display, FromStr};
#[derive(Copy, Clone, Debug, TryFromPrimitive, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, TryFromPrimitive, PartialEq, Eq, Hash, Display, FromStr)]
#[repr(u16)] #[repr(u16)]
pub enum Key { pub enum Key {
KeyReserved = 0, KeyReserved = 0,
@ -118,11 +119,11 @@ pub enum Key {
KeyMute = 113, KeyMute = 113,
KeyVolumeDown = 114, KeyVolumeDown = 114,
KeyVolumeUp = 115, KeyVolumeUp = 115,
KeyPower = 116 /* SC System Power Down */, KeyPower = 116, /* SC System Power Down */
KeyKpEqual = 117, KeyKpEqual = 117,
KeyKpPlusMinus = 118, KeyKpPlusMinus = 118,
KeyPause = 119, KeyPause = 119,
KeyScale = 120 /* AL Compiz Scale (Expose) */, KeyScale = 120, /* AL Compiz Scale (Expose) */
KeyKpComma = 121, KeyKpComma = 121,
KeyHangeul = 122, KeyHangeul = 122,
KeyHanja = 123, KeyHanja = 123,
@ -130,38 +131,38 @@ pub enum Key {
KeyLeftMeta = 125, KeyLeftMeta = 125,
KeyRightMeta = 126, KeyRightMeta = 126,
KeyCompose = 127, KeyCompose = 127,
KeyStop = 128 /* AC Stop */, KeyStop = 128, /* AC Stop */
KeyAgain = 129, KeyAgain = 129,
KeyProps = 130 /* AC Properties */, KeyProps = 130, /* AC Properties */
KeyUndo = 131 /* AC Undo */, KeyUndo = 131, /* AC Undo */
KeyFront = 132, KeyFront = 132,
KeyCopy = 133 /* AC Copy */, KeyCopy = 133, /* AC Copy */
KeyOpen = 134 /* AC Open */, KeyOpen = 134, /* AC Open */
KeyPaste = 135 /* AC Paste */, KeyPaste = 135, /* AC Paste */
KeyFind = 136 /* AC Search */, KeyFind = 136, /* AC Search */
KeyCut = 137 /* AC Cut */, KeyCut = 137, /* AC Cut */
KeyHelp = 138 /* AL Integrated Help Center */, KeyHelp = 138, /* AL Integrated Help Center */
KeyMenu = 139 /* Menu (show menu) */, KeyMenu = 139, /* Menu (show menu) */
KeyCalc = 140 /* AL Calculator */, KeyCalc = 140, /* AL Calculator */
KeySetup = 141, KeySetup = 141,
KeySleep = 142 /* SC System Sleep */, KeySleep = 142, /* SC System Sleep */
KeyWakeup = 143 /* System Wake Up */, KeyWakeup = 143, /* System Wake Up */
KeyFile = 144 /* AL Local Machine Browser */, KeyFile = 144, /* AL Local Machine Browser */
KeySendfile = 145, KeySendfile = 145,
KeyDeleteFile = 146, KeyDeleteFile = 146,
KeyXfer = 147, KeyXfer = 147,
KeyProg1 = 148, KeyProg1 = 148,
KeyProg2 = 149, KeyProg2 = 149,
KeyWww = 150 /* AL Internet Browser */, KeyWww = 150, /* AL Internet Browser */
KeyMsDos = 151, KeyMsDos = 151,
KeyCoffee = 152 /* AL Terminal Lock/Screensaver */, KeyCoffee = 152, /* AL Terminal Lock/Screensaver */
KeyDirection = 153, KeyDirection = 153,
KeyCycleWindows = 154, KeyCycleWindows = 154,
KeyMail = 155, KeyMail = 155,
KeyBookmarks = 156 /* AC Bookmarks */, KeyBookmarks = 156, /* AC Bookmarks */
KeyComputer = 157, KeyComputer = 157,
KeyBack = 158 /* AC Back */, KeyBack = 158, /* AC Back */
KeyForward = 159 /* AC Forward */, KeyForward = 159, /* AC Forward */
KeyCloseCd = 160, KeyCloseCd = 160,
KeyEjectCd = 161, KeyEjectCd = 161,
KeyEjectCloseCd = 162, KeyEjectCloseCd = 162,
@ -171,20 +172,20 @@ pub enum Key {
KeyStopCd = 166, KeyStopCd = 166,
KeyRecord = 167, KeyRecord = 167,
KeyRewind = 168, KeyRewind = 168,
KeyPhone = 169 /* Media Select Telephone */, KeyPhone = 169, /* Media Select Telephone */
KeyIso = 170, KeyIso = 170,
KeyConfig = 171 /* AL Consumer Control Configuration */, KeyConfig = 171, /* AL Consumer Control Configuration */
KeyHomepage = 172 /* AC Home */, KeyHomepage = 172, /* AC Home */
KeyRefresh = 173 /* AC Refresh */, KeyRefresh = 173, /* AC Refresh */
KeyExit = 174 /* AC Exit */, KeyExit = 174, /* AC Exit */
KeyMove = 175, KeyMove = 175,
KeyEdit = 176, KeyEdit = 176,
KeyScrollUp = 177, KeyScrollUp = 177,
KeyScrollDown = 178, KeyScrollDown = 178,
KeyKpLeftParen = 179, KeyKpLeftParen = 179,
KeyKpRightParen = 180, KeyKpRightParen = 180,
KeyNew = 181 /* AC New */, KeyNew = 181, /* AC New */
KeyRedo = 182 /* AC Redo/Repeat */, KeyRedo = 182, /* AC Redo/Repeat */
KeyF13 = 183, KeyF13 = 183,
KeyF14 = 184, KeyF14 = 184,
KeyF15 = 185, KeyF15 = 185,
@ -201,13 +202,13 @@ pub enum Key {
KeyPauseCd = 201, KeyPauseCd = 201,
KeyProg3 = 202, KeyProg3 = 202,
KeyProg4 = 203, KeyProg4 = 203,
KeyDashboard = 204 /* AL Dashboard */, KeyDashboard = 204, /* AL Dashboard */
KeySuspend = 205, KeySuspend = 205,
KeyClose = 206 /* AC Close */, KeyClose = 206, /* AC Close */
KeyPlay = 207, KeyPlay = 207,
KeyFastForward = 208, KeyFastForward = 208,
KeyBassBoost = 209, KeyBassBoost = 209,
KeyPrint = 210 /* AC Print */, KeyPrint = 210, /* AC Print */
KeyHp = 211, KeyHp = 211,
KeyCamera = 212, KeyCamera = 212,
KeySound = 213, KeySound = 213,
@ -300,13 +301,13 @@ pub enum Key {
BtnToolFinger = 0x145, BtnToolFinger = 0x145,
BtnToolMouse = 0x146, BtnToolMouse = 0x146,
BtnToolLens = 0x147, BtnToolLens = 0x147,
BtnToolQuintTap =0x148 /* Five fingers on trackpad */, BtnToolQuintTap = 0x148, /* Five fingers on trackpad */
BtnTouch = 0x14a, BtnTouch = 0x14a,
BtnStylus = 0x14b, BtnStylus = 0x14b,
BtnStylus2 = 0x14c, BtnStylus2 = 0x14c,
BtnToolDoubleTap = 0x14d, BtnToolDoubleTap = 0x14d,
BtnToolTripleTap = 0x14e, BtnToolTripleTap = 0x14e,
BtnToolQuadTap =0x14f /* Four fingers on trackpad */, BtnToolQuadTap = 0x14f, /* Four fingers on trackpad */
BtnGearDown = 0x150, BtnGearDown = 0x150,
BtnGearUp = 0x151, BtnGearUp = 0x151,
KeyOk = 0x160, KeyOk = 0x160,
@ -315,15 +316,15 @@ pub enum Key {
KeyClear = 0x163, KeyClear = 0x163,
KeyPower2 = 0x164, KeyPower2 = 0x164,
KeyOption = 0x165, KeyOption = 0x165,
KeyInfo = 0x166 /* AL OEM Features/Tips/Tutorial */, KeyInfo = 0x166, /* AL OEM Features/Tips/Tutorial */
KeyTime = 0x167, KeyTime = 0x167,
KeyVendor = 0x168, KeyVendor = 0x168,
KeyArchive = 0x169, KeyArchive = 0x169,
KeyProgram = 0x16a /* Media Select Program Guide */, KeyProgram = 0x16a, /* Media Select Program Guide */
KeyChannel = 0x16b, KeyChannel = 0x16b,
KeyFavorites = 0x16c, KeyFavorites = 0x16c,
KeyEpg = 0x16d, KeyEpg = 0x16d,
KeyPvr = 0x16e /* Media Select Home */, KeyPvr = 0x16e, /* Media Select Home */
KeyMhp = 0x16f, KeyMhp = 0x16f,
KeyLanguage = 0x170, KeyLanguage = 0x170,
KeyTitle = 0x171, KeyTitle = 0x171,
@ -333,36 +334,36 @@ pub enum Key {
KeyMode = 0x175, KeyMode = 0x175,
KeyKeyboard = 0x176, KeyKeyboard = 0x176,
KeyScreen = 0x177, KeyScreen = 0x177,
KeyPc = 0x178 /* Media Select Computer */, KeyPc = 0x178, /* Media Select Computer */
KeyTv = 0x179 /* Media Select TV */, KeyTv = 0x179, /* Media Select TV */
KeyTv2 = 0x17a /* Media Select Cable */, KeyTv2 = 0x17a, /* Media Select Cable */
KeyVcr = 0x17b /* Media Select VCR */, KeyVcr = 0x17b, /* Media Select VCR */
KeyVcr2 = 0x17c /* VCR Plus */, KeyVcr2 = 0x17c, /* VCR Plus */
KeySat = 0x17d /* Media Select Satellite */, KeySat = 0x17d, /* Media Select Satellite */
KeySat2 = 0x17e, KeySat2 = 0x17e,
KeyCd = 0x17f /* Media Select CD */, KeyCd = 0x17f, /* Media Select CD */
KeyTape = 0x180 /* Media Select Tape */, KeyTape = 0x180, /* Media Select Tape */
KeyRadio = 0x181, KeyRadio = 0x181,
KeyTuner = 0x182 /* Media Select Tuner */, KeyTuner = 0x182, /* Media Select Tuner */
KeyPlayer = 0x183, KeyPlayer = 0x183,
KeyText = 0x184, KeyText = 0x184,
KeyDvd = 0x185 /* Media Select DVD */, KeyDvd = 0x185, /* Media Select DVD */
KeyAux = 0x186, KeyAux = 0x186,
KeyMp3 = 0x187, KeyMp3 = 0x187,
KeyAudio = 0x188 /* AL Audio Browser */, KeyAudio = 0x188, /* AL Audio Browser */
KeyVideo = 0x189 /* AL Movie Browser */, KeyVideo = 0x189, /* AL Movie Browser */
KeyDirectory = 0x18a, KeyDirectory = 0x18a,
KeyList = 0x18b, KeyList = 0x18b,
KeyMemo = 0x18c /* Media Select Messages */, KeyMemo = 0x18c, /* Media Select Messages */
KeyCalendar = 0x18d, KeyCalendar = 0x18d,
KeyRed = 0x18e, KeyRed = 0x18e,
KeyGreen = 0x18f, KeyGreen = 0x18f,
KeyYellow = 0x190, KeyYellow = 0x190,
KeyBlue = 0x191, KeyBlue = 0x191,
KeyChannelUp = 0x192 /* Channel Increment */, KeyChannelUp = 0x192, /* Channel Increment */
KeyChannelDown = 0x193 /* Channel Decrement */, KeyChannelDown = 0x193, /* Channel Decrement */
KeyFirst = 0x194, KeyFirst = 0x194,
KeyLast = 0x195 /* Recall Last */, KeyLast = 0x195, /* Recall Last */
KeyAb = 0x196, KeyAb = 0x196,
KeyNext = 0x197, KeyNext = 0x197,
KeyRestart = 0x198, KeyRestart = 0x198,
@ -373,33 +374,33 @@ pub enum Key {
KeyDigits = 0x19d, KeyDigits = 0x19d,
KeyTeen = 0x19e, KeyTeen = 0x19e,
KeyTwen = 0x19f, KeyTwen = 0x19f,
KeyVideophone = 0x1a0 /* Media Select Video Phone */, KeyVideophone = 0x1a0, /* Media Select Video Phone */
KeyGames = 0x1a1 /* Media Select Games */, KeyGames = 0x1a1, /* Media Select Games */
KeyZoomIn = 0x1a2 /* AC Zoom In */, KeyZoomIn = 0x1a2, /* AC Zoom In */
KeyZoomOut = 0x1a3 /* AC Zoom Out */, KeyZoomOut = 0x1a3, /* AC Zoom Out */
KeyZoomReset = 0x1a4 /* AC Zoom */, KeyZoomReset = 0x1a4, /* AC Zoom */
KeyWordProcessor =0x1a5 /* AL Word Processor */, KeyWordProcessor = 0x1a5, /* AL Word Processor */
KeyEditor = 0x1a6 /* AL Text Editor */, KeyEditor = 0x1a6, /* AL Text Editor */
KeySpreadsheet = 0x1a7 /* AL Spreadsheet */, KeySpreadsheet = 0x1a7, /* AL Spreadsheet */
KeyGraphicsEditor =0x1a8 /* AL Graphics Editor */, KeyGraphicsEditor = 0x1a8, /* AL Graphics Editor */
KeyPresentation =0x1a9 /* AL Presentation App */, KeyPresentation = 0x1a9, /* AL Presentation App */
KeyDatabase = 0x1aa /* AL Database App */, KeyDatabase = 0x1aa, /* AL Database App */
KeyNews = 0x1ab /* AL Newsreader */, KeyNews = 0x1ab, /* AL Newsreader */
KeyVoiceMail = 0x1ac /* AL Voicemail */, KeyVoiceMail = 0x1ac, /* AL Voicemail */
KeyAddressBook = 0x1ad /* AL Contacts/Address Book */, KeyAddressBook = 0x1ad, /* AL Contacts/Address Book */
KeyMessenger = 0x1ae /* AL Instant Messaging */, KeyMessenger = 0x1ae, /* AL Instant Messaging */
KeyDisplayToggle =0x1af /* Turn display (LCD) on and off */, KeyDisplayToggle = 0x1af, /* Turn display (LCD) on and off */
KeySpellcheck = 0x1b0 /* AL Spell Check */, KeySpellcheck = 0x1b0, /* AL Spell Check */
KeyLogoff = 0x1b1 /* AL Logoff */, KeyLogoff = 0x1b1, /* AL Logoff */
KeyDollar = 0x1b2, KeyDollar = 0x1b2,
KeyEuro = 0x1b3, KeyEuro = 0x1b3,
KeyFrameBack = 0x1b4 /* Consumer - transport controls */, KeyFrameBack = 0x1b4, /* Consumer - transport controls */
KeyFrameForward = 0x1b5, KeyFrameForward = 0x1b5,
KeyContextMenu =0x1b6 /* GenDesc - system context menu */, KeyContextMenu = 0x1b6, /* GenDesc - system context menu */
KeyMediaRepeat =0x1b7 /* Consumer - transport control */, KeyMediaRepeat = 0x1b7, /* Consumer - transport control */
Key10ChannelsUp =0x1b8 /* 10 channels up (10+) */, Key10ChannelsUp = 0x1b8, /* 10 channels up (10+) */
Key10ChannelsDown =0x1b9 /* 10 channels down (10-) */, Key10ChannelsDown = 0x1b9, /* 10 channels down (10-) */
KeyImages = 0x1ba /* AL Image Browser */, KeyImages = 0x1ba, /* AL Image Browser */
KeyDelEol = 0x1c0, KeyDelEol = 0x1c0,
KeyDelEos = 0x1c1, KeyDelEos = 0x1c1,
KeyInsLine = 0x1c2, KeyInsLine = 0x1c2,
@ -435,8 +436,8 @@ pub enum Key {
KeyBrlDot8 = 0x1f8, KeyBrlDot8 = 0x1f8,
KeyBrlDot9 = 0x1f9, KeyBrlDot9 = 0x1f9,
KeyBrlDot10 = 0x1fa, KeyBrlDot10 = 0x1fa,
KeyNumeric0 = 0x200 /* used by phones, remote controls, */, KeyNumeric0 = 0x200, /* used by phones, remote controls, */
KeyNumeric1 = 0x201 /* and other keypads */, KeyNumeric1 = 0x201, /* and other keypads */
KeyNumeric2 = 0x202, KeyNumeric2 = 0x202,
KeyNumeric3 = 0x203, KeyNumeric3 = 0x203,
KeyNumeric4 = 0x204, KeyNumeric4 = 0x204,
@ -448,8 +449,8 @@ pub enum Key {
KeyNumericStar = 0x20a, KeyNumericStar = 0x20a,
KeyNumericPound = 0x20b, KeyNumericPound = 0x20b,
KeyCameraFocus = 0x210, KeyCameraFocus = 0x210,
KeyWpsButton = 0x211 /* WiFi Protected Setup key */, KeyWpsButton = 0x211, /* WiFi Protected Setup key */
KeyTouchpadToggle =0x212 /* Request switch touchpad on or off */, KeyTouchpadToggle = 0x212, /* Request switch touchpad on or off */
KeyTouchpadOn = 0x213, KeyTouchpadOn = 0x213,
KeyTouchpadOff = 0x214, KeyTouchpadOff = 0x214,
KeyCameraZoomIn = 0x215, KeyCameraZoomIn = 0x215,
@ -460,22 +461,22 @@ pub enum Key {
KeyCameraRight = 0x21a, KeyCameraRight = 0x21a,
KeyAttendantOn = 0x21b, KeyAttendantOn = 0x21b,
KeyAttendantOff = 0x21c, KeyAttendantOff = 0x21c,
KeyAttendantToggle =0x21d /* Attendant call on or off */, KeyAttendantToggle = 0x21d, /* Attendant call on or off */
KeyLightsToggle =0x21e /* Reading light on or off */, KeyLightsToggle = 0x21e, /* Reading light on or off */
BtnDpadUp = 0x220, BtnDpadUp = 0x220,
BtnDpadDown = 0x221, BtnDpadDown = 0x221,
BtnDpadLeft = 0x222, BtnDpadLeft = 0x222,
BtnDpadRight = 0x223, BtnDpadRight = 0x223,
KeyAlsToggle = 0x230 /* Ambient light sensor */, KeyAlsToggle = 0x230, /* Ambient light sensor */
KeyButtonConfig = 0x240 /* AL Button Configuration */, KeyButtonConfig = 0x240, /* AL Button Configuration */
KeyTaskManager = 0x241 /* AL Task/Project Manager */, KeyTaskManager = 0x241, /* AL Task/Project Manager */
KeyJournal = 0x242 /* AL Log/Journal/Timecard */, KeyJournal = 0x242, /* AL Log/Journal/Timecard */
KeyControlPanel = 0x243 /* AL Control Panel */, KeyControlPanel = 0x243, /* AL Control Panel */
KeyAppSelect = 0x244 /* AL Select Task/Application */, KeyAppSelect = 0x244, /* AL Select Task/Application */
KeyScreenSaver = 0x245 /* AL Screen Saver */, KeyScreenSaver = 0x245, /* AL Screen Saver */
KeyVoiceCommand = 0x246 /* Listening Voice Command */, KeyVoiceCommand = 0x246, /* Listening Voice Command */
KeyBrightnessMin = 0x250 /* Set Brightness to Minimum */, KeyBrightnessMin = 0x250, /* Set Brightness to Minimum */
KeyBrightnessMax = 0x251 /* Set Brightness to Maximum */, KeyBrightnessMax = 0x251, /* Set Brightness to Maximum */
KeyKbdinputassistPrev = 0x260, KeyKbdinputassistPrev = 0x260,
KeyKbdinputassistNext = 0x261, KeyKbdinputassistNext = 0x261,
KeyKbdinputassistPrevgroup = 0x262, KeyKbdinputassistPrevgroup = 0x262,
@ -564,7 +565,7 @@ impl Key {
Key::KeyX => true, Key::KeyX => true,
Key::KeyY => true, Key::KeyY => true,
Key::KeyZ => true, Key::KeyZ => true,
_ => false _ => false,
} }
} }
} }

View file

@ -1,20 +1,27 @@
use evdev::Device;
pub use keycodes::Key;
use parse_display::{Display, FromStr, ParseError};
use std::collections::HashSet;
use std::convert::TryFrom;
use std::fmt::{self, Display};
use std::str::FromStr;
use std::sync::mpsc::{channel, Receiver};
use std::sync::{Arc, Mutex};
mod keycodes; mod keycodes;
pub use keycodes::Key; #[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Display, FromStr)]
use std::collections::HashSet;
#[derive(Clone, Copy, Debug)]
pub enum Modifier { pub enum Modifier {
AnyAlt, Alt,
LeftAlt, LeftAlt,
RightAlt, RightAlt,
AnyCtrl, Ctrl,
LeftCtrl, LeftCtrl,
RightCtrl, RightCtrl,
AnyShift, Shift,
LeftShift, LeftShift,
RightShift, RightShift,
AnyMeta, Meta,
LeftMeta, LeftMeta,
RightMeta, RightMeta,
} }
@ -22,31 +29,93 @@ pub enum Modifier {
impl Modifier { impl Modifier {
pub fn is_modifier(&self, key: Key) -> bool { pub fn is_modifier(&self, key: Key) -> bool {
match self { match self {
Modifier::AnyAlt => key == Key::KeyLeftAlt || key == Key::KeyRightAlt, Modifier::Alt => key == Key::KeyLeftAlt || key == Key::KeyRightAlt,
Modifier::LeftAlt => key == Key::KeyLeftAlt, Modifier::LeftAlt => key == Key::KeyLeftAlt,
Modifier::RightAlt => key == Key::KeyRightAlt, Modifier::RightAlt => key == Key::KeyRightAlt,
Modifier::AnyCtrl => key == Key::KeyLeftCtrl || key == Key::KeyRightCtrl, Modifier::Ctrl => key == Key::KeyLeftCtrl || key == Key::KeyRightCtrl,
Modifier::LeftCtrl => key == Key::KeyLeftCtrl, Modifier::LeftCtrl => key == Key::KeyLeftCtrl,
Modifier::RightCtrl => key == Key::KeyRightCtrl, Modifier::RightCtrl => key == Key::KeyRightCtrl,
Modifier::AnyMeta => key == Key::KeyLeftMeta || key == Key::KeyRightMeta, Modifier::Meta => key == Key::KeyLeftMeta || key == Key::KeyRightMeta,
Modifier::LeftMeta => key == Key::KeyLeftMeta, Modifier::LeftMeta => key == Key::KeyLeftMeta,
Modifier::RightMeta => key == Key::KeyRightMeta, Modifier::RightMeta => key == Key::KeyRightMeta,
Modifier::AnyShift => key == Key::KeyLeftshift || key == Key::KeyRightshift, Modifier::Shift => key == Key::KeyLeftshift || key == Key::KeyRightshift,
Modifier::LeftShift => key == Key::KeyLeftshift, Modifier::LeftShift => key == Key::KeyLeftshift,
Modifier::RightShift => key == Key::KeyRightshift, Modifier::RightShift => key == Key::KeyRightshift,
} }
} }
} }
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct ModifierList(Vec<Modifier>);
impl Display for ModifierList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for modifier in self.0.iter() {
write!(f, "<{}>", modifier)?;
}
Ok(())
}
}
impl FromStr for ModifierList {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ModifierList(
s.split('>')
.filter(|part| !part.is_empty())
.map(|part| {
if !part.starts_with('<') {
Err(ParseError::with_message("Invalid modifier"))
} else {
Ok(part[1..].parse::<Modifier>()?)
}
})
.collect::<Result<Vec<Modifier>, ParseError>>()?,
))
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, Display, FromStr)]
#[display("{modifiers}-{key}")]
pub struct Shortcut { pub struct Shortcut {
pub modifiers: Vec<Modifier>, modifiers: ModifierList,
pub key: Key, key: Key,
}
#[test]
fn test_shortcut_format() {
assert_eq!(
"<Ctrl>-KeyP",
format!("{}", Shortcut::new(vec![Modifier::Ctrl], Key::KeyP))
);
assert_eq!(
"<LeftCtrl><LeftAlt>-KeyLeft",
format!(
"{}",
Shortcut::new(vec![Modifier::LeftCtrl, Modifier::LeftAlt], Key::KeyLeft)
)
);
assert_eq!(
Shortcut::from_str("<LeftCtrl><LeftAlt>-KeyLeft").unwrap(),
Shortcut::new(vec![Modifier::LeftCtrl, Modifier::LeftAlt], Key::KeyLeft)
);
}
impl Shortcut {
pub fn new(modifiers: Vec<Modifier>, key: Key) -> Self {
Shortcut {
modifiers: ModifierList(modifiers),
key,
}
}
} }
impl Shortcut { impl Shortcut {
pub fn is_triggered(&self, active_keys: &HashSet<Key>) -> bool { pub fn is_triggered(&self, active_keys: &HashSet<Key>) -> bool {
for modifier in &self.modifiers { for modifier in &self.modifiers.0 {
if active_keys.iter().any(|key| modifier.is_modifier(*key)) { if active_keys.iter().any(|key| modifier.is_modifier(*key)) {
break; break;
} }
@ -57,3 +126,59 @@ impl Shortcut {
active_keys.contains(&self.key) active_keys.contains(&self.key)
} }
} }
pub struct ShortcutListener {
shortcuts: Arc<Mutex<HashSet<Shortcut>>>,
}
impl ShortcutListener {
pub fn new() -> Self {
ShortcutListener {
shortcuts: Arc::default(),
}
}
pub fn listen(&self, mut device: Device) -> Receiver<Shortcut> {
let (tx, rx) = channel();
let shortcuts = self.shortcuts.clone();
std::thread::spawn(move || {
let mut active_keys = HashSet::new();
loop {
let mut got_event = false;
for ev in device.events().unwrap() {
got_event = true;
if let Ok(key) = Key::try_from(ev.code) {
match ev.value {
1 => active_keys.insert(key),
0 => active_keys.remove(&key),
_ => false,
};
}
}
if got_event {
for shortcut in shortcuts.lock().unwrap().iter() {
if shortcut.is_triggered(&active_keys) {
tx.send(shortcut.clone()).unwrap()
}
}
}
}
});
rx
}
pub fn add(&self, shortcut: Shortcut) {
self.shortcuts.lock().unwrap().insert(shortcut);
}
pub fn remove(&self, shortcut: Shortcut) {
self.shortcuts.lock().unwrap().remove(&shortcut);
}
}

View file

@ -1,45 +1,109 @@
use crate::keyboard::{Key, Modifier, Shortcut, ShortcutListener};
use evdev::Device; use evdev::Device;
use main_error::MainError; use main_error::MainError;
use std::collections::HashSet; use std::collections::HashSet;
use crate::keyboard::{Key, Shortcut, Modifier};
use std::convert::TryFrom; use std::convert::TryFrom;
use dbus::blocking::LocalConnection;
use dbus::channel::Sender;
use dbus::tree::{Factory, MethodErr};
use std::error::Error;
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;
mod keyboard; mod keyboard;
fn main() -> Result<(), MainError> { fn main() -> Result<(), MainError> {
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
let mut device = if args.len() > 1 { let device = if args.len() > 1 {
Device::open(&args[1])? Device::open(&args[1])?
} else { } else {
eprintln!("Usage {} </dev/input/...>", args[0]); eprintln!("Usage {} </dev/input/...>", args[0]);
return Ok(()); return Ok(());
}; };
let mut keys = HashSet::new(); // let shortcut = Shortcut::new(vec![Modifier::Ctrl, Modifier::Ctrl], Key::KeyP);
let shortcut = Shortcut {
modifiers: vec![Modifier::AnyCtrl, Modifier::AnyCtrl],
key: Key::KeyP
};
let listener = ShortcutListener::new();
// listener.add(shortcut);
let rx = listener.listen(device);
// Let's start by starting up a connection to the session bus and request a name.
let mut connection: LocalConnection = LocalConnection::new_session()?;
connection.request_name("nl.icewind.shortcutd", false, true, false)?;
// The choice of factory tells us what type of tree we want,
// and if we want any extra data inside. We pick the simplest variant.
let f = Factory::new_fn::<()>();
// We create the signal first, since we'll need it in both inside the method callback
// and when creating the tree.
let signal = Arc::new(f.signal("ShortcutTriggered", ()).sarg::<&str, _>("sender"));
let signal2 = signal.clone();
let signal3 = signal.clone();
// We create a tree with one object path inside and make that path introspectable.
let tree = f
.tree(())
.add(
f.object_path("/shortcut", ()).introspectable().add(
// We add an interface to the object path...
f.interface("nl.icewind.shortcutd", ())
.add_m(
// ...and a method inside the interface.
f.method("Register", (), move |m| {
// This is the callback that will be called when another peer on the bus calls our method.
// the callback receives "MethodInfo" struct and can return either an error, or a list of
// messages to send back.
let name: &str = m.msg.read1()?;
match Shortcut::from_str(name) {
Ok(shortcut) => {
let s = format!("Ok: {}", shortcut);
listener.add(shortcut);
let mret = m.msg.method_return().append1(s);
Ok(vec![mret])
}
Err(_) => Err(MethodErr::invalid_arg("Failed to parse shortcut")),
}
// let s = format!("Hello {}!", name);
// let mret = m.msg.method_return().append1(s);
//
// // let sig = signal
// // .msg(m.path.get_name(), m.iface.get_name())
// // .append1(&*name);
//
// // Two messages will be returned - one is the method return (and should always be there),
// // and in our case we also have a signal we want to send at the same time.
// Ok(vec![mret, sig])
// Our method has one output argument and one input argument.
})
.outarg::<&str, _>("reply")
.inarg::<&str, _>("name"), // We also add the signal to the interface. This is mainly for introspection.
)
.add_s(signal2), // Also add the root path, to help introspection from debugging tools.
),
)
.add(f.object_path("/", ()).introspectable());
// We add the tree to the connection so that incoming method calls will be handled.
tree.start_receive(&connection);
// Serve clients forever.
loop { loop {
let mut got_event = false; connection.process(Duration::from_millis(50))?;
for ev in device.events()? { while let Ok(shortcut) = rx.try_recv() {
got_event = true; connection
.send(
if let Ok(key) = Key::try_from(ev.code) { signal3
match ev.value { .msg(&"/shortcut".into(), &"nl.icewind.shortcutd".into())
1 => keys.insert(key), .append1(&format!("{}", shortcut)),
0 => keys.remove(&key), )
_ => false, .unwrap();
};
}
}
if got_event {
if shortcut.is_triggered(&keys) {
println!("triggered");
}
} }
} }