diff --git a/.github/workflows/compile-rust.yml b/.github/workflows/compile-rust.yml index c7ade72..bf9252a 100644 --- a/.github/workflows/compile-rust.yml +++ b/.github/workflows/compile-rust.yml @@ -21,13 +21,13 @@ jobs: artifact_name: target/debug/legion-kb-rgb asset_name: legion-kb-rgb-linux triplet: x64-linux - vcpkgCommitId: 'ab67d6306b5e9af69684af5ec761c97731e75834' + vcpkgCommitId: '335a153de3e398208df4d25eff89d831727bc5da' - name: windows os: windows-latest artifact_name: target/debug/legion-kb-rgb.exe asset_name: legion-kb-rgb-windows triplet: x64-windows-static - vcpkgCommitId: 'ab67d6306b5e9af69684af5ec761c97731e75834' + vcpkgCommitId: '335a153de3e398208df4d25eff89d831727bc5da' env: VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }} @@ -55,7 +55,7 @@ jobs: if [ "$RUNNER_OS" == "Linux" ]; then sudo apt-get update -y sudo apt install -y libunwind-dev - sudo apt-get install -y libx11-dev nasm libdbus-1-dev libudev-dev libxcb-randr0-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libxi-dev libxtst-dev libusb-1.0-0-dev + sudo apt-get install -y libx11-dev nasm libdbus-1-dev libudev-dev libxcb-randr0-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libxi-dev libxtst-dev libusb-1.0-0-dev libpango1.0-dev elif [ "$RUNNER_OS" == "macOS" ]; then brew install nasm elif [ "$RUNNER_OS" == "Windows" ]; then diff --git a/.github/workflows/release-rust.yml b/.github/workflows/release-rust.yml index ebe8e1b..22bac67 100644 --- a/.github/workflows/release-rust.yml +++ b/.github/workflows/release-rust.yml @@ -21,13 +21,13 @@ jobs: artifact_name: target/release/legion-kb-rgb asset_name: legion-kb-rgb-linux triplet: x64-linux - vcpkgCommitId: 'ab67d6306b5e9af69684af5ec761c97731e75834' + vcpkgCommitId: '335a153de3e398208df4d25eff89d831727bc5da' - name: windows os: windows-latest artifact_name: target/release/legion-kb-rgb.exe asset_name: legion-kb-rgb-windows triplet: x64-windows-static - vcpkgCommitId: 'ab67d6306b5e9af69684af5ec761c97731e75834' + vcpkgCommitId: '335a153de3e398208df4d25eff89d831727bc5da' env: VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }} @@ -55,7 +55,7 @@ jobs: if [ "$RUNNER_OS" == "Linux" ]; then sudo apt-get update -y sudo apt install -y libunwind-dev - sudo apt-get install -y libx11-dev nasm libdbus-1-dev libudev-dev libxcb-randr0-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libxi-dev libxtst-dev libusb-1.0-0-dev + sudo apt-get install -y libx11-dev nasm libdbus-1-dev libudev-dev libxcb-randr0-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libxi-dev libxtst-dev libusb-1.0-0-dev libpango1.0-dev elif [ "$RUNNER_OS" == "macOS" ]; then brew install nasm elif [ "$RUNNER_OS" == "Windows" ]; then diff --git a/Cargo.lock b/Cargo.lock index 531db65..6f771ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -517,6 +517,29 @@ dependencies = [ "syn 2.0.77", ] +[[package]] +name = "atk" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4af014b17dd80e8af9fa689b2d4a211ddba6eb583c1622f35d0cb543f6b17e4" +dependencies = [ + "atk-sys", + "glib 0.18.5", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "251e0b7d90e33e0ba930891a505a9a35ece37b2dd37a14f3ffc306c13b980009" +dependencies = [ + "glib-sys 0.18.1", + "gobject-sys 0.18.0", + "libc", + "system-deps 6.1.1", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -725,6 +748,9 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde 1.0.210", +] [[package]] name = "bitstream-io" @@ -860,6 +886,31 @@ dependencies = [ "serde 1.0.210", ] +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.6.0", + "cairo-sys-rs", + "glib 0.18.5", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys 0.18.1", + "libc", + "system-deps 6.1.1", +] + [[package]] name = "calloop" version = "0.12.4" @@ -1067,37 +1118,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "cocoa" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" -dependencies = [ - "bitflags 1.3.2", - "block", - "cocoa-foundation", - "core-foundation 0.9.4", - "core-graphics", - "foreign-types 0.5.0", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" -dependencies = [ - "bitflags 1.3.2", - "block", - "core-foundation 0.9.4", - "core-graphics-types", - "foreign-types 0.3.2", - "libc", - "objc", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1188,12 +1208,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "concat-string" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7439becb5fafc780b6f4de382b1a7a3e70234afe783854a4702ee8adbb838609" - [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1257,7 +1271,20 @@ checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "core-graphics-types", + "core-graphics-types 0.1.3", + "foreign-types 0.5.0", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", "foreign-types 0.5.0", "libc", ] @@ -1273,6 +1300,17 @@ dependencies = [ "libc", ] +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", + "libc", +] + [[package]] name = "cpufeatures" version = "0.2.8" @@ -1379,26 +1417,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "dbus-codegen" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a49da9fdfbe872d4841d56605dc42efa5e6ca3291299b87f44e1cde91a28617c" -dependencies = [ - "clap 2.34.0", - "dbus", - "xml-rs", -] - -[[package]] -name = "dbus-tree" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f456e698ae8e54575e19ddb1f9b7bce2298568524f215496b248eb9498b4f508" -dependencies = [ - "dbus", -] - [[package]] name = "deranged" version = "0.3.11" @@ -1454,6 +1472,15 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -1464,6 +1491,18 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -1528,6 +1567,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "dpi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" + [[package]] name = "dtoa" version = "0.4.8" @@ -1893,6 +1938,16 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset 0.9.0", + "rustc_version", +] + [[package]] name = "filetime" version = "0.2.21" @@ -1914,17 +1969,6 @@ dependencies = [ "toml 0.5.11", ] -[[package]] -name = "find-winsdk" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8cbf17b871570c1f8612b763bac3e86290602bcf5dc3c5ce657e0e1e9071d9e" -dependencies = [ - "serde 1.0.210", - "serde_derive", - "winreg 0.5.1", -] - [[package]] name = "flate2" version = "1.0.26" @@ -2137,6 +2181,64 @@ dependencies = [ "slab", ] +[[package]] +name = "gdk" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5ba081bdef3b75ebcdbfc953699ed2d7417d6bd853347a42a37d76406a33646" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib 0.18.5", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib 0.18.5", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", + "libc", + "system-deps 6.1.1", +] + +[[package]] +name = "gdk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ff856cb3386dae1703a920f803abafcc580e9b5f711ca62ed1620c25b51ff2" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", + "libc", + "pango-sys", + "pkg-config", + "system-deps 6.1.1", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -2197,6 +2299,38 @@ version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib 0.18.5", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys 0.18.1", + "gobject-sys 0.18.0", + "libc", + "system-deps 6.1.1", + "winapi", +] + [[package]] name = "gl_generator" version = "0.14.0" @@ -2220,13 +2354,36 @@ dependencies = [ "futures-executor", "futures-task", "futures-util", - "glib-macros", - "glib-sys", - "gobject-sys", + "glib-macros 0.10.1", + "glib-sys 0.10.1", + "gobject-sys 0.10.0", "libc", "once_cell", ] +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.6.0", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros 0.18.5", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror", +] + [[package]] name = "glib-macros" version = "0.10.1" @@ -2243,6 +2400,20 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 2.0.2", + "proc-macro-error", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + [[package]] name = "glib-sys" version = "0.10.1" @@ -2253,6 +2424,16 @@ dependencies = [ "system-deps 1.3.2", ] +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps 6.1.1", +] + [[package]] name = "glob" version = "0.3.1" @@ -2342,11 +2523,22 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "952133b60c318a62bf82ee75b93acc7e84028a093e06b9e27981c2b6fe68218c" dependencies = [ - "glib-sys", + "glib-sys 0.10.1", "libc", "system-deps 1.3.2", ] +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys 0.18.1", + "libc", + "system-deps 6.1.1", +] + [[package]] name = "gpu-alloc" version = "0.6.0" @@ -2410,9 +2602,9 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "glib", - "glib-sys", - "gobject-sys", + "glib 0.10.3", + "glib-sys 0.10.1", + "gobject-sys 0.10.0", "gstreamer-sys", "libc", "muldiv", @@ -2432,9 +2624,9 @@ dependencies = [ "bitflags 1.3.2", "futures-core", "futures-sink", - "glib", - "glib-sys", - "gobject-sys", + "glib 0.10.3", + "glib-sys 0.10.1", + "gobject-sys 0.10.0", "gstreamer", "gstreamer-app-sys", "gstreamer-base", @@ -2449,7 +2641,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "813f64275c9e7b33b828b9efcf9dfa64b95996766d4de996e84363ac65b87e3d" dependencies = [ - "glib-sys", + "glib-sys 0.10.1", "gstreamer-base-sys", "gstreamer-sys", "libc", @@ -2463,9 +2655,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bafd01c56f59cb10f4b5a10f97bb4bdf8c2b2784ae5b04da7e2d400cf6e6afcf" dependencies = [ "bitflags 1.3.2", - "glib", - "glib-sys", - "gobject-sys", + "glib 0.10.3", + "glib-sys 0.10.1", + "gobject-sys 0.10.0", "gstreamer", "gstreamer-base-sys", "gstreamer-sys", @@ -2478,8 +2670,8 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4b7b6dc2d6e160a1ae28612f602bd500b3fa474ce90bf6bb2f08072682beef5" dependencies = [ - "glib-sys", - "gobject-sys", + "glib-sys 0.10.1", + "gobject-sys 0.10.0", "gstreamer-sys", "libc", "system-deps 1.3.2", @@ -2491,8 +2683,8 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1f154082d01af5718c5f8a8eb4f565a4ea5586ad8833a8fc2c2aa6844b601d" dependencies = [ - "glib-sys", - "gobject-sys", + "glib-sys 0.10.1", + "gobject-sys 0.10.0", "libc", "system-deps 1.3.2", ] @@ -2506,9 +2698,9 @@ dependencies = [ "bitflags 1.3.2", "futures-channel", "futures-util", - "glib", - "glib-sys", - "gobject-sys", + "glib 0.10.3", + "glib-sys 0.10.1", + "gobject-sys 0.10.0", "gstreamer", "gstreamer-base", "gstreamer-base-sys", @@ -2524,14 +2716,66 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92347e46438007d6a2386302125f62cb9df6769cdacb931af5c0f12c1ee21de4" dependencies = [ - "glib-sys", - "gobject-sys", + "glib-sys 0.10.1", + "gobject-sys 0.10.0", "gstreamer-base-sys", "gstreamer-sys", "libc", "system-deps 1.3.2", ] +[[package]] +name = "gtk" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93c4f5e0e20b60e10631a5f06da7fe3dda744b05ad0ea71fee2f47adf865890c" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib 0.18.5", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771437bf1de2c1c0b496c11505bdf748e26066bbe942dfc8f614c9460f6d7722" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys 0.18.1", + "gobject-sys 0.18.0", + "libc", + "pango-sys", + "system-deps 6.1.1", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6063efb63db582968fb7df72e1ae68aa6360dcfb0a75143f34fc7d616bad75e" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + [[package]] name = "half" version = "2.2.1" @@ -3032,6 +3276,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.6.0", + "serde 1.0.210", + "unicode-segmentation", +] + [[package]] name = "khronos-egl" version = "6.0.0" @@ -3049,18 +3304,6 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" -[[package]] -name = "ksni" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4934310bdd016e55725482b8d35ac0c16fd058c1b955d8959aa2d953b918c85b" -dependencies = [ - "dbus", - "dbus-codegen", - "dbus-tree", - "thiserror", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -3093,6 +3336,7 @@ dependencies = [ "egui_file", "error-stack", "fast_image_resize", + "gtk", "image 0.25.2", "legion-rgb-driver", "open", @@ -3106,9 +3350,8 @@ dependencies = [ "strum_macros 0.26.4", "sysinfo 0.31.4", "thiserror", - "tray-item", + "tray-icon", "winapi", - "windres", ] [[package]] @@ -3119,6 +3362,30 @@ dependencies = [ "thiserror", ] +[[package]] +name = "libappindicator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" +dependencies = [ + "glib 0.18.5", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" +dependencies = [ + "gtk-sys", + "libloading 0.7.4", + "once_cell", +] + [[package]] name = "libc" version = "0.2.158" @@ -3177,6 +3444,25 @@ dependencies = [ "walkdir", ] +[[package]] +name = "libxdo" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00333b8756a3d28e78def82067a377de7fa61b24909000aeaa2b446a948d14db" +dependencies = [ + "libxdo-sys", +] + +[[package]] +name = "libxdo-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23b9e7e2b7831bbd8aac0bbeeeb7b68cbebc162b227e7052e8e55829a09212" +dependencies = [ + "libc", + "x11", +] + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -3237,7 +3523,7 @@ source = "git+https://github.com/rustdesk-org/machine-uid#381ff579c1dc3a6c54db9d dependencies = [ "bindgen 0.59.2", "cc", - "winreg 0.11.0", + "winreg", ] [[package]] @@ -3328,7 +3614,7 @@ checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" dependencies = [ "bitflags 2.6.0", "block", - "core-graphics-types", + "core-graphics-types 0.1.3", "foreign-types 0.5.0", "log", "objc", @@ -3372,6 +3658,26 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "muda" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8123dfd4996055ac9b15a60ad263b44b01e539007523ad7a4a533a3d93b0591" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "libxdo", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation", + "once_cell", + "png", + "thiserror", + "windows-sys 0.59.0", +] + [[package]] name = "muldiv" version = "0.2.1" @@ -3695,17 +4001,6 @@ dependencies = [ "malloc_buf", ] -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - [[package]] name = "objc-sys" version = "0.2.0-beta.2" @@ -3847,15 +4142,6 @@ dependencies = [ "objc2-metal", ] -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - [[package]] name = "object" version = "0.30.4" @@ -3926,6 +4212,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "orbclient" version = "0.3.45" @@ -3980,12 +4272,6 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" -[[package]] -name = "padlock" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c10569378a1dacd9f30dbe7ae49e054d2c45dc2f8ee49899903e09c3924e8b6f" - [[package]] name = "palette" version = "0.6.1" @@ -4010,6 +4296,31 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib 0.18.5", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys 0.18.1", + "gobject-sys 0.18.0", + "libc", + "system-deps 6.1.1", +] + [[package]] name = "parking" version = "2.1.0" @@ -4310,7 +4621,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.10", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", ] [[package]] @@ -5048,6 +5369,7 @@ dependencies = [ "log", "ndk-context", "num_cpus", + "pkg-config", "serde 1.0.210", "serde_json 1.0.128", "target_build_utils", @@ -5836,14 +6158,14 @@ dependencies = [ "serde 1.0.210", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.10", ] [[package]] name = "toml_datetime" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde 1.0.210", ] @@ -5858,7 +6180,18 @@ dependencies = [ "serde 1.0.210", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.4.7", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.5.0", + "toml_datetime", + "winnow 0.5.40", ] [[package]] @@ -5916,20 +6249,23 @@ dependencies = [ ] [[package]] -name = "tray-item" -version = "0.10.0" +name = "tray-icon" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59d4bd406170690dc30eabb3badc67a085beaf9b2c3b1923afcc9c26a2191353" +checksum = "7c92af36a182b46206723bdf8a7942e20838cde1cf062e5b97854d57eb01763b" dependencies = [ - "cocoa", - "core-graphics", - "ksni", - "libc", - "objc", - "objc-foundation", - "objc_id", - "padlock", - "windows-sys 0.52.0", + "core-graphics 0.24.0", + "crossbeam-channel", + "dirs", + "libappindicator", + "muda", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation", + "once_cell", + "png", + "thiserror", + "windows-sys 0.59.0", ] [[package]] @@ -6460,7 +6796,7 @@ dependencies = [ "ash", "bitflags 2.6.0", "cfg_aliases", - "core-graphics-types", + "core-graphics-types 0.1.3", "glow", "glutin_wgl_sys", "gpu-alloc", @@ -6903,16 +7239,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windres" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82115619221b2b66001a39088b8059d171b1f9005a00d6a10c6e8a71a30a4cdc" -dependencies = [ - "concat-string", - "find-winsdk", -] - [[package]] name = "winit" version = "0.29.15" @@ -6927,7 +7253,7 @@ dependencies = [ "calloop 0.12.4", "cfg_aliases", "core-foundation 0.9.4", - "core-graphics", + "core-graphics 0.23.2", "cursor-icon", "icrate", "js-sys", @@ -6972,13 +7298,12 @@ dependencies = [ ] [[package]] -name = "winreg" -version = "0.5.1" +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ - "serde 1.0.210", - "winapi", + "memchr", ] [[package]] diff --git a/README.md b/README.md index 2dab19f..0e38bb4 100644 --- a/README.md +++ b/README.md @@ -182,14 +182,19 @@ This program has been tested to work on: - [Rust](https://www.rust-lang.org/tools/install) - [Git](https://git-scm.com/downloads) -- On Linux, you'll need additional dependencies: -#### Ubuntu +#### Linux + +##### Ubuntu ```sh sudo apt-get install -y libclang-dev libxcb-shm0-dev libusb-1.0-0-dev libx11-dev nasm libdbus-1-dev libudev-dev libxcb-randr0-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libxi-dev libxtst-dev ``` +#### Windows + +Follow [this guide](https://gtk-rs.org/gtk4-rs/stable/latest/book/installation_windows.html#pkg-config) but build GTK3 instead of GTK4. + ### Using `cargo-make` Works on both Windows and Linux. diff --git a/app/Cargo.toml b/app/Cargo.toml index e7809a5..ed632b6 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -55,27 +55,26 @@ open = "5.3.0" error-stack = "0.5.0" winapi = { version = "0.3.9", features = ["consoleapi", "wincon"] } +tray-icon = "0.19.1" +gtk = "0.18.1" + # Fix versions to stop cargo from yelling about dependency resolution # Dependabot alerts - -[target.'cfg(target_os = "windows")'.dependencies] -tray-item = { version = "0.10.0" } - -[target.'cfg(target_os = "linux")'.dependencies] -tray-item = { version = "0.10.0", features = ["ksni"] } - -[build-dependencies] -windres = "0.2.2" +# HACK: Add a dummy feature to the program because rust-analyzer doesn't want +# to enable linux-pkg-config itself for whatever reason +[features] +scrap-pkg-config = ["scrap/linux-pkg-config"] [package.metadata.vcpkg] git = "https://github.com/microsoft/vcpkg" -rev = "f6a5d4e" +rev = "335a153" [package.metadata.vcpkg.target] -x86_64-unknown-linux-gnu = { dependencies = ["libvpx", "libyuv"] } +x86_64-unknown-linux-gnu = { dependencies = ["libvpx", "libyuv", "aom"] } x86_64-pc-windows-msvc = { dependencies = [ "libvpx:x64-windows-static", "libyuv:x64-windows-static", + "aom:x64-windows-static", ] } diff --git a/app/build.rs b/app/build.rs deleted file mode 100644 index e55a2e1..0000000 --- a/app/build.rs +++ /dev/null @@ -1,9 +0,0 @@ -extern crate windres; - -fn main() { - #[cfg(target_os = "windows")] - { - use windres::Build; - Build::new().compile("./res/resources.rc").unwrap(); - } -} diff --git a/app/src/gui/mod.rs b/app/src/gui/mod.rs index 28ae34b..3d05735 100644 --- a/app/src/gui/mod.rs +++ b/app/src/gui/mod.rs @@ -1,6 +1,11 @@ use std::{mem, process, thread, time::Duration}; -use crossbeam_channel::{Receiver, Sender}; +#[cfg(target_os = "linux")] +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; + use device_query::{DeviceQuery, Keycode}; #[cfg(debug_assertions)] use eframe::egui::style::DebugOptions; @@ -12,13 +17,17 @@ use eframe::{ }; use strum::IntoEnumIterator; -use tray_item::{IconSource, TrayItem}; +#[cfg(target_os = "linux")] +use tray_icon::menu::MenuEvent; +#[cfg(not(target_os = "linux"))] +use tray_icon::{menu::MenuEvent, TrayIcon}; use crate::{ cli::OutputType, effects::{self, custom_effect::CustomEffect, EffectManager, ManagerCreationError}, enums::Effects, persist::Settings, + tray::{self, QUIT_ID, SHOW_ID}, }; use self::{effect_options::EffectOptions, menu_bar::MenuBarState, profile_list::ProfileList, style::Theme}; @@ -33,10 +42,16 @@ pub struct App { settings: Settings, instance_not_unique: bool, - window_open_rx: Option>, - // The tray struct needs to be kept from being dropped for the tray to appear on windows + gui_tx: crossbeam_channel::Sender, + gui_rx: crossbeam_channel::Receiver, + + // For Linux + #[cfg(target_os = "linux")] + has_tray: Arc, + // The tray struct needs to be kept from being dropped for the tray to appear on windows/mac // If this is none it will be assumed there's no tray regardless of cause - tray: Option, + #[cfg(not(target_os = "linux"))] + tray: Option, manager: Option, profile_changed: bool, @@ -63,7 +78,9 @@ pub enum CustomEffectState { } impl App { - pub fn new(output: OutputType, tx: Sender, rx: Receiver) -> Self { + pub fn new(output: OutputType) -> Self { + let (gui_tx, gui_rx) = crossbeam_channel::unbounded::(); + let manager_result = EffectManager::new(effects::OperationMode::Gui); let instance_not_unique = if let Err(err) = &manager_result { @@ -77,12 +94,17 @@ impl App { let settings: Settings = Settings::load(); let profiles = settings.profiles.clone(); + let gui_tx_c = gui_tx.clone(); // Default app state let mut app = Self { settings, instance_not_unique, - window_open_rx: Some(rx), + gui_tx, + gui_rx, + #[cfg(target_os = "linux")] + has_tray: Arc::new(AtomicBool::new(false)), + #[cfg(not(target_os = "linux"))] tray: None, manager, @@ -90,7 +112,7 @@ impl App { profile_changed: true, custom_effect: CustomEffectState::default(), - menu_bar: MenuBarState::new(tx), + menu_bar: MenuBarState::new(gui_tx_c), profile_list: ProfileList::new(profiles), effect_options: EffectOptions::default(), global_rgb: [0; 3], @@ -108,51 +130,56 @@ impl App { app } - pub fn init(mut self, cc: &CreationContext<'_>, gui_sender: Sender, hide_window: bool) -> Self { + pub fn init(mut self, cc: &CreationContext<'_>, hide_window: bool) -> Self { cc.egui_ctx.send_viewport_cmd(ViewportCommand::Visible(!hide_window)); - //Create the tray icon + #[cfg(not(target_os = "linux"))] + { + self.tray = tray::build_tray(true); + } + // Since egui uses winit under the hood and doesn't use gtk on Linux, and we need gtk for + // the tray icon to show up, we need to spawn a thread + // where we initialize gtk and create the tray_icon #[cfg(target_os = "linux")] - let tray_icon = load_tray_icon(include_bytes!("../../res/trayIcon.ico")); + { + let has_tray_c = self.has_tray.clone(); - #[cfg(target_os = "linux")] - let tray_result = TrayItem::new("Keyboard RGB", tray_icon); + std::thread::spawn(move || { + gtk::init().unwrap(); - #[cfg(target_os = "windows")] - let tray_result = TrayItem::new("Keyboard RGB", IconSource::Resource("trayIcon")); + let tray_icon = tray::build_tray(true); + has_tray_c.store(tray_icon.is_some(), Ordering::SeqCst); - self.tray = if let Ok(mut tray) = tray_result { - let mut is_err = false; + gtk::main(); + }); + } - let egui_ctx = cc.egui_ctx.clone(); - is_err |= tray - .add_menu_item("Show", move || { + let egui_ctx = cc.egui_ctx.clone(); + let gui_tx = self.gui_tx.clone(); + std::thread::spawn(move || loop { + // println!("a"); + // if let Ok(event) = TrayIconEvent::receiver().try_recv() { + // println!("{:?}", event); + // } + + if let Ok(event) = MenuEvent::receiver().recv() { + if event.id == SHOW_ID { + println!("show"); egui_ctx.request_repaint(); egui_ctx.send_viewport_cmd(ViewportCommand::Visible(true)); egui_ctx.send_viewport_cmd(ViewportCommand::Focus); - }) - .is_err(); - - let quit_sender = gui_sender.clone(); - let egui_ctx = cc.egui_ctx.clone(); - is_err |= tray - .add_menu_item("Quit", move || { + } else if event.id == QUIT_ID { + println!("quit"); egui_ctx.request_repaint(); - quit_sender.send(GuiMessage::Quit).unwrap() - }) - .is_err(); - if !is_err { - Some(tray) - } else { - None + let _ = gui_tx.send(GuiMessage::Quit); + } } - } else { - None - }; + }); let ctx = cc.egui_ctx.clone(); + let gui_tx_c = self.gui_tx.clone(); if self.manager.is_some() { thread::spawn(move || { let state = device_query::DeviceState::new(); @@ -163,7 +190,7 @@ impl App { if keys.contains(&Keycode::LMeta) && keys.contains(&Keycode::RAlt) { if !lock_switching { - let _ = gui_sender.send(GuiMessage::CycleProfiles); + let _ = gui_tx_c.send(GuiMessage::CycleProfiles); ctx.request_repaint(); lock_switching = true; } @@ -184,12 +211,10 @@ impl App { impl eframe::App for App { fn update(&mut self, ctx: &eframe::egui::Context, _frame: &mut eframe::Frame) { - if let Some(rx) = &self.window_open_rx { - if let Ok(message) = rx.try_recv() { - match message { - GuiMessage::CycleProfiles => self.cycle_profiles(), - GuiMessage::Quit => self.exit_app(), - } + if let Ok(message) = self.gui_rx.try_recv() { + match message { + GuiMessage::CycleProfiles => self.cycle_profiles(), + GuiMessage::Quit => self.exit_app(), } } @@ -297,7 +322,15 @@ impl eframe::App for App { } if ctx.input(|i| i.viewport().close_requested()) { - if self.tray.is_some() && !std::env::var("WAYLAND_DISPLAY").is_ok() { + #[cfg(target_os = "linux")] + if self.has_tray.load(Ordering::Relaxed) && !std::env::var("WAYLAND_DISPLAY").is_ok() { + ctx.send_viewport_cmd(ViewportCommand::CancelClose); + ctx.send_viewport_cmd(ViewportCommand::Visible(false)); + } else { + // Close normally + } + #[cfg(not(target_os = "linux"))] + if self.tray.is_some() { ctx.send_viewport_cmd(ViewportCommand::CancelClose); ctx.send_viewport_cmd(ViewportCommand::Visible(false)); } else { @@ -360,17 +393,3 @@ impl App { } } } - -#[cfg(target_os = "linux")] -#[must_use] -pub fn load_tray_icon(image_data: &[u8]) -> IconSource { - let image = image::load_from_memory(image_data).unwrap(); - let image_buffer = image.to_rgba8(); - let pixels = image_buffer.into_flat_samples().samples; - - IconSource::Data { - data: pixels, - width: image.width() as i32, - height: image.height() as i32, - } -} diff --git a/app/src/main.rs b/app/src/main.rs index c94691d..db2bb10 100644 --- a/app/src/main.rs +++ b/app/src/main.rs @@ -9,12 +9,13 @@ mod enums; mod gui; mod persist; mod profile; +mod tray; mod util; use cli::{GuiCommand, OutputType}; use color_eyre::{eyre::eyre, Result}; use eframe::{egui::IconData, epaint::Vec2}; -use gui::{App, GuiMessage}; +use gui::App; const WINDOW_SIZE: Vec2 = Vec2::new(500., 400.); @@ -92,12 +93,9 @@ fn start_ui(output_type: OutputType, hide_window: bool) { ..eframe::NativeOptions::default() }; - let (gui_sender, gui_receiver) = crossbeam_channel::unbounded::(); + let app = App::new(output_type); - let gui_sender_clone = gui_sender.clone(); - let app = App::new(output_type, gui_sender_clone, gui_receiver); - - eframe::run_native("Legion RGB", native_options, Box::new(move |cc| Ok(Box::new(app.init(cc, gui_sender, hide_window))))).unwrap(); + eframe::run_native("Legion RGB", native_options, Box::new(move |cc| Ok(Box::new(app.init(cc, hide_window))))).unwrap(); } #[must_use] diff --git a/app/src/tray.rs b/app/src/tray.rs new file mode 100644 index 0000000..f071011 --- /dev/null +++ b/app/src/tray.rs @@ -0,0 +1,53 @@ +use tray_icon::{ + menu::{Menu, MenuItem}, + Icon, TrayIcon, TrayIconBuilder, +}; + +pub const SHOW_ID: &str = "tray-show"; +pub const QUIT_ID: &str = "tray-quit"; + +struct TrayMenuItems { + show: MenuItem, + quit: MenuItem, +} + +impl TrayMenuItems { + fn build() -> Self { + let show = MenuItem::with_id(SHOW_ID, "Show", true, None); + let quit = MenuItem::with_id(QUIT_ID, "Quit", true, None); + + Self { show, quit } + } +} + +fn build_tray_menu(items: &TrayMenuItems, has_gui: bool) -> Menu { + let menu = Menu::new(); + if has_gui { + menu.append_items(&[&items.show]).unwrap(); + } + menu.append_items(&[&items.quit]).unwrap(); + menu +} + +pub fn build_tray(has_gui: bool) -> Option { + let items = TrayMenuItems::build(); + let menu = build_tray_menu(&items, has_gui); + + TrayIconBuilder::new() + .with_tooltip("Legion Keyboard Control") + .with_icon(load_tray_icon(include_bytes!("../res/trayIcon.ico"))) + .with_menu(Box::new(menu)) + .build() + .ok() +} + +#[must_use] +fn load_tray_icon(image_data: &[u8]) -> Icon { + use tray_icon::Icon; + + let image = image::load_from_memory(image_data).unwrap(); + let image_buffer = image.to_rgba8(); + let pixels = image_buffer.into_flat_samples().samples; + + Icon::from_rgba(pixels, image.width(), image.height()).unwrap() +} diff --git a/flake.nix b/flake.nix index 8810ec5..176e79c 100644 --- a/flake.nix +++ b/flake.nix @@ -51,6 +51,12 @@ xorg.libXi libusb1 expat + + # Tray icon + pango + gtk3 + gdk-pixbuf + xdotool ]; # Libraries needed at runtime @@ -62,6 +68,9 @@ libGL wayland libxkbcommon + + # Tray icon + libayatana-appindicator ] ++ sharedDeps; envVars = rec {