From bc6aa191c09b6ce973b6327b368e338c6eeaf7fd Mon Sep 17 00:00:00 2001 From: Haim Gelfenbeyn Date: Sat, 21 Oct 2023 19:05:26 -0400 Subject: [PATCH 1/4] Copy & paste from #94, since that PR was abandoned by its author. --- Cargo.lock | 102 +++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/platform/wake_displays.rs | 19 +++++++ 3 files changed, 120 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0839288..ddec940 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,6 +42,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "cc" version = "1.0.83" @@ -51,6 +61,12 @@ dependencies = [ "libc", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -111,6 +127,12 @@ dependencies = [ "libc", ] +[[package]] +name = "custom_derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" + [[package]] name = "ddc" version = "0.2.2" @@ -227,6 +249,7 @@ dependencies = [ "serde_json", "shell-words", "simplelog", + "uinput", "winapi", ] @@ -251,6 +274,12 @@ dependencies = [ "nom 3.2.1", ] +[[package]] +name = "enum_derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "406ac2a8c9eedf8af9ee1489bee9e50029278a6456c740f7454cf8a158abc816" + [[package]] name = "foreign-types" version = "0.5.0" @@ -278,13 +307,19 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + [[package]] name = "getrandom" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] @@ -341,6 +376,21 @@ dependencies = [ "mach2", ] +[[package]] +name = "ioctl-sys" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2c4b26352496eaaa8ca7cfa9bd99e93419d3f7983dc6e99c2a35fe9e33504a" + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "itoa" version = "1.0.9" @@ -359,6 +409,16 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "libudev" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea626d3bdf40a1c5aee3bcd4f40826970cae8d80a8fec934c82a63840094dcfe" +dependencies = [ + "libc", + "libudev-sys", +] + [[package]] name = "libudev-sys" version = "0.1.4" @@ -464,6 +524,20 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "nix" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7fd5681d13fda646462cfbd4e5f2051279a89a544d50eb98c365b507246839f" +dependencies = [ + "bitflags", + "bytes", + "cfg-if 0.1.10", + "gcc", + "libc", + "void", +] + [[package]] name = "nom" version = "3.2.1" @@ -627,7 +701,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "ordered-multimap", ] @@ -778,6 +852,30 @@ dependencies = [ "libudev-sys", ] +[[package]] +name = "uinput" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b074d55c90be32a89a063fe3f944c0ceed0a8e3291369a99809f18fa326685b" +dependencies = [ + "custom_derive", + "enum_derive", + "libc", + "libudev", + "nix", + "uinput-sys", +] + +[[package]] +name = "uinput-sys" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aabddd8174ccadd600afeab346bb276cb1db5fafcf6a7c5c5708b8cc4b2cac7" +dependencies = [ + "ioctl-sys", + "libc", +] + [[package]] name = "unicode-ident" version = "1.0.12" diff --git a/Cargo.toml b/Cargo.toml index fd49642..196e05d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ ddc-macos = "^0.2" [target.'cfg(target_os = "linux")'.dependencies] ddc-i2c = "^0.2" nvapi = "^0.1" +uinput = "^0.1" [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "^0.3", features = ["winuser", "libloaderapi"] } diff --git a/src/platform/wake_displays.rs b/src/platform/wake_displays.rs index 2567032..c05140b 100644 --- a/src/platform/wake_displays.rs +++ b/src/platform/wake_displays.rs @@ -40,6 +40,25 @@ pub fn wake_displays() -> Result<()> { #[cfg(target_os = "linux")] pub fn wake_displays() -> Result<()> { + use anyhow::Context; + use std::{thread, time}; + use uinput::{Device, event::keyboard}; + + fn make_kbd_device() -> Result { + Ok(uinput::default()? + .name("display-switch")? + .event(uinput::event::Keyboard::All)? + .create()?) + } + + let mut device = make_kbd_device().context("Couldn't wake displays: couldn't configure uinput")?; + + // This sleep appears to be necessary based on testing. + // Possibly X does not immediately recognize the new device? + thread::sleep(time::Duration::from_secs(1)); + + device.click(&keyboard::Key::RightAlt)?; + device.synchronize()?; Ok(()) } From af0d63b002fa596480141157e2482ef6ade0660e Mon Sep 17 00:00:00 2001 From: Haim Gelfenbeyn Date: Sun, 22 Oct 2023 07:21:55 -0400 Subject: [PATCH 2/4] More descriptive error in wake display tests --- .github/workflows/build.yml | 1 + src/platform/wake_displays.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eb94d03..1f8c872 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,7 @@ on: [push, pull_request] env: CARGO_TERM_COLOR: always + RUST_BACKTRACE: 1 jobs: build: diff --git a/src/platform/wake_displays.rs b/src/platform/wake_displays.rs index c05140b..233f988 100644 --- a/src/platform/wake_displays.rs +++ b/src/platform/wake_displays.rs @@ -68,6 +68,7 @@ mod tests { #[test] fn test_wake_displays() { - assert!(wake_displays().is_ok()); + let waked = wake_displays(); + assert!(waked.is_ok(), "Couldn't wake displays: {:?}", waked); } } From 578132248a34ae5149e83ce188287e3c0dbf20eb Mon Sep 17 00:00:00 2001 From: Haim Gelfenbeyn Date: Sun, 22 Oct 2023 08:00:40 -0400 Subject: [PATCH 3/4] Move mouse instead of keyboard input --- .github/workflows/build.yml | 2 +- src/platform/wake_displays.rs | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1f8c872..fd01ad0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: [push, pull_request] env: CARGO_TERM_COLOR: always - RUST_BACKTRACE: 1 + RUST_BACKTRACE: full jobs: build: diff --git a/src/platform/wake_displays.rs b/src/platform/wake_displays.rs index 233f988..46e7255 100644 --- a/src/platform/wake_displays.rs +++ b/src/platform/wake_displays.rs @@ -42,22 +42,28 @@ pub fn wake_displays() -> Result<()> { pub fn wake_displays() -> Result<()> { use anyhow::Context; use std::{thread, time}; - use uinput::{Device, event::keyboard}; + use uinput::event::controller::Controller::Mouse; + use uinput::event::controller::Mouse::Left; + use uinput::event::Event::{Controller, Relative}; + use uinput::event::relative::Position::X; + use uinput::event::relative::Relative::Position; - fn make_kbd_device() -> Result { - Ok(uinput::default()? + let mut device = uinput::default()? .name("display-switch")? - .event(uinput::event::Keyboard::All)? - .create()?) - } + // It's necessary to enable any mouse button. Otherwise Relative events would not work. + .event(Controller(Mouse(Left)))? + .event(Relative(Position(X)))? + .create()?; - let mut device = make_kbd_device().context("Couldn't wake displays: couldn't configure uinput")?; // This sleep appears to be necessary based on testing. // Possibly X does not immediately recognize the new device? thread::sleep(time::Duration::from_secs(1)); - device.click(&keyboard::Key::RightAlt)?; + device.send(X, -1)?; + device.synchronize()?; + thread::sleep(time::Duration::from_millis(50)); + device.send(X, 1)?; device.synchronize()?; Ok(()) } From 77fe3faeb976d412df162fb3dccba60a0661812d Mon Sep 17 00:00:00 2001 From: Haim Gelfenbeyn Date: Sun, 22 Oct 2023 08:26:19 -0400 Subject: [PATCH 4/4] Ignore permission denied errors in tests: Github actions cannot control the mouse. --- src/platform/wake_displays.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/platform/wake_displays.rs b/src/platform/wake_displays.rs index 46e7255..eb30e37 100644 --- a/src/platform/wake_displays.rs +++ b/src/platform/wake_displays.rs @@ -75,6 +75,8 @@ mod tests { #[test] fn test_wake_displays() { let waked = wake_displays(); - assert!(waked.is_ok(), "Couldn't wake displays: {:?}", waked); + if let Err(err) = &waked { + assert!(err.to_string() == "Permission denied", "Couldn't wake displays: {:?}", err); + } } }