mirror of
https://github.com/Noratrieb/clippyboard.git
synced 2026-01-14 09:55:04 +01:00
it's all coming together
This commit is contained in:
parent
0c5b9d26e1
commit
ea487d598c
4 changed files with 390 additions and 234 deletions
228
Cargo.lock
generated
228
Cargo.lock
generated
|
|
@ -127,6 +127,15 @@ dependencies = [
|
|||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-activity"
|
||||
version = "0.6.0"
|
||||
|
|
@ -303,7 +312,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -338,7 +347,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -484,7 +493,7 @@ checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -610,19 +619,13 @@ dependencies = [
|
|||
"egui_extras",
|
||||
"eyre",
|
||||
"serde",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
"wl-clipboard-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codegen"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"strong-xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.12.0"
|
||||
|
|
@ -775,7 +778,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -977,7 +980,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -998,7 +1001,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1101,7 +1104,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1159,7 +1162,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1210,7 +1213,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1587,12 +1590,6 @@ dependencies = [
|
|||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jetscii"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47f142fe24a9c9944451e8349de0a56af5f3e7226dc46f3ed4d4ecc0b85af75e"
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
version = "0.21.1"
|
||||
|
|
@ -1740,6 +1737,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
|
||||
dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.5"
|
||||
|
|
@ -1916,6 +1922,15 @@ dependencies = [
|
|||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.50.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
|
|
@ -1945,7 +1960,7 @@ dependencies = [
|
|||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2368,7 +2383,7 @@ dependencies = [
|
|||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
|
|
@ -2399,7 +2414,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2608,6 +2623,23 @@ dependencies = [
|
|||
"thiserror 2.0.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
|
||||
|
||||
[[package]]
|
||||
name = "renderdoc-sys"
|
||||
version = "1.1.0"
|
||||
|
|
@ -2709,7 +2741,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2720,7 +2752,16 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2843,30 +2884,6 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
||||
|
||||
[[package]]
|
||||
name = "strong-xml"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d19fb3a618e2f1039e32317c9f525e6d45c55af704ec7c429aa74412419bebf"
|
||||
dependencies = [
|
||||
"jetscii",
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
"strong-xml-derive",
|
||||
"xmlparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strong-xml-derive"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92c781f499321613b112be5d9338189ef1ed19689a01edd23d923ea57ad5c7e1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.26.3"
|
||||
|
|
@ -2886,18 +2903,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2919,7 +2925,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2970,7 +2976,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2981,7 +2987,16 @@ checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3069,7 +3084,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3079,6 +3094,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
|
||||
dependencies = [
|
||||
"matchers",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex-automata",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3161,6 +3206,12 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
|
|
@ -3215,7 +3266,7 @@ dependencies = [
|
|||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
|
@ -3250,7 +3301,7 @@ checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
|
@ -3562,13 +3613,6 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "willy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
@ -3677,7 +3721,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3688,7 +3732,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3699,7 +3743,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3710,7 +3754,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4152,12 +4196,6 @@ version = "0.8.27"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7"
|
||||
|
||||
[[package]]
|
||||
name = "xmlparser"
|
||||
version = "0.13.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.0"
|
||||
|
|
@ -4178,7 +4216,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
|
|
@ -4233,7 +4271,7 @@ checksum = "dc6821851fa840b708b4cbbaf6241868cabc85a2dc22f426361b0292bfc0b836"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
"zbus-lockstep",
|
||||
"zbus_xml",
|
||||
"zvariant",
|
||||
|
|
@ -4248,7 +4286,7 @@ dependencies = [
|
|||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
"zbus_names",
|
||||
"zvariant",
|
||||
"zvariant_utils",
|
||||
|
|
@ -4296,7 +4334,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4316,7 +4354,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
|
|
@ -4350,7 +4388,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4391,7 +4429,7 @@ dependencies = [
|
|||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
|
|
@ -4404,6 +4442,6 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn 2.0.106",
|
||||
"syn",
|
||||
"winnow",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
[workspace]
|
||||
members = [".", "willy", "willy/codegen"]
|
||||
|
||||
[package]
|
||||
name = "clippyboard"
|
||||
version = "0.1.0"
|
||||
|
|
@ -13,6 +10,8 @@ eframe = "0.32.2"
|
|||
egui_extras = { version = "0.32.2", features = ["image"] }
|
||||
eyre = "0.6.12"
|
||||
serde = "1.0.219"
|
||||
tracing = { version = "0.1.41", features = ["attributes"] }
|
||||
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
|
||||
wayland-client = "0.31.11"
|
||||
wayland-protocols = { version = "0.32.9", features = ["staging"] }
|
||||
wl-clipboard-rs = "0.9.2"
|
||||
|
|
|
|||
351
src/daemon.rs
351
src/daemon.rs
|
|
@ -2,24 +2,19 @@ use super::HistoryItem;
|
|||
use super::MAX_ENTRY_SIZE;
|
||||
use eframe::egui::ahash::HashSet;
|
||||
use eyre::Context;
|
||||
use eyre::bail;
|
||||
use std::collections::HashMap;
|
||||
use std::io::BufWriter;
|
||||
use std::io::Read;
|
||||
use std::io::{BufReader, BufWriter, PipeWriter, Read, Write};
|
||||
use std::os::fd::AsFd;
|
||||
use std::os::unix::net::UnixListener;
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::atomic::AtomicU64;
|
||||
use std::sync::{Arc, Mutex, OnceLock, atomic::AtomicU64};
|
||||
use std::time::Duration;
|
||||
use std::time::SystemTime;
|
||||
use wayland_client::Dispatch;
|
||||
use wayland_client::Proxy;
|
||||
use wayland_client::backend::ObjectId;
|
||||
use wayland_client::event_created_child;
|
||||
use wayland_client::globals::GlobalListContents;
|
||||
use wayland_client::globals::registry_queue_init;
|
||||
use tracing::info;
|
||||
use tracing::warn;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use wayland_client::{Dispatch, Proxy, QueueHandle, backend::ObjectId, event_created_child};
|
||||
use wayland_client::protocol::wl_registry::WlRegistry;
|
||||
use wayland_client::protocol::wl_seat::WlSeat;
|
||||
use wayland_protocols::ext::data_control::v1::client::ext_data_control_device_v1;
|
||||
|
|
@ -29,14 +24,18 @@ use wayland_protocols::ext::data_control::v1::client::ext_data_control_device_v1
|
|||
use wayland_protocols::ext::data_control::v1::client::ext_data_control_manager_v1::ExtDataControlManagerV1;
|
||||
use wayland_protocols::ext::data_control::v1::client::ext_data_control_offer_v1;
|
||||
use wayland_protocols::ext::data_control::v1::client::ext_data_control_offer_v1::ExtDataControlOfferV1;
|
||||
use wl_clipboard_rs::paste::ClipboardType;
|
||||
use wl_clipboard_rs::paste::MimeType;
|
||||
use wl_clipboard_rs::paste::Seat;
|
||||
use wayland_protocols::ext::data_control::v1::client::ext_data_control_source_v1;
|
||||
use wayland_protocols::ext::data_control::v1::client::ext_data_control_source_v1::ExtDataControlSourceV1;
|
||||
|
||||
struct HistoryState {
|
||||
next_item_id: Arc<AtomicU64>,
|
||||
last_copied_item_id: Arc<AtomicU64>,
|
||||
items: Arc<Mutex<Vec<HistoryItem>>>,
|
||||
struct SharedState {
|
||||
next_item_id: AtomicU64,
|
||||
// for deduplication because the event stream will tell us that we just copied something :)
|
||||
last_copied_item_id: AtomicU64,
|
||||
items: Mutex<Vec<HistoryItem>>,
|
||||
|
||||
data_control_manager: OnceLock<ExtDataControlManagerV1>,
|
||||
data_control_devices: Mutex<HashMap</*seat global name */ u32, ExtDataControlDeviceV1>>,
|
||||
qh: QueueHandle<WlState>,
|
||||
}
|
||||
|
||||
struct InProgressOffer {
|
||||
|
|
@ -52,22 +51,80 @@ struct CurrentSelection {
|
|||
}
|
||||
|
||||
struct WlState {
|
||||
history_state: Arc<HistoryState>,
|
||||
shared_state: Arc<SharedState>,
|
||||
|
||||
/// wl_seat that arrived before the data control manager so we weren't able to grab their device immediatly.
|
||||
deferred_seats: Vec<WlSeat>,
|
||||
|
||||
offers: HashMap<ObjectId, InProgressOffer>,
|
||||
current_primary_selection: Option<CurrentSelection>,
|
||||
current_selection: Option<CurrentSelection>,
|
||||
}
|
||||
|
||||
impl Dispatch<WlRegistry, GlobalListContents> for WlState {
|
||||
impl Dispatch<WlRegistry, ()> for WlState {
|
||||
fn event(
|
||||
_state: &mut Self,
|
||||
_proxy: &WlRegistry,
|
||||
_event: <WlRegistry as wayland_client::Proxy>::Event,
|
||||
_data: &GlobalListContents,
|
||||
state: &mut Self,
|
||||
proxy: &WlRegistry,
|
||||
event: <WlRegistry as wayland_client::Proxy>::Event,
|
||||
_data: &(),
|
||||
_conn: &wayland_client::Connection,
|
||||
_qhandle: &wayland_client::QueueHandle<Self>,
|
||||
qhandle: &wayland_client::QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
wayland_client::protocol::wl_registry::Event::Global {
|
||||
name,
|
||||
interface,
|
||||
version: _, // we only need version 1
|
||||
} => {
|
||||
if interface == WlSeat::interface().name {
|
||||
info!("A new seat was connected");
|
||||
let seat: WlSeat = proxy.bind(name, 1, qhandle, ());
|
||||
|
||||
match state.shared_state.data_control_manager.get() {
|
||||
None => {
|
||||
state.deferred_seats.push(seat);
|
||||
}
|
||||
Some(manager) => {
|
||||
let device = manager.get_data_device(&seat, qhandle, ());
|
||||
state
|
||||
.shared_state
|
||||
.data_control_devices
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(name, device);
|
||||
}
|
||||
}
|
||||
} else if interface == ExtDataControlManagerV1::interface().name {
|
||||
let manager: ExtDataControlManagerV1 = proxy.bind(name, 1, qhandle, ());
|
||||
|
||||
for seat in state.deferred_seats.drain(..) {
|
||||
let device = manager.get_data_device(&seat, qhandle, ());
|
||||
state
|
||||
.shared_state
|
||||
.data_control_devices
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(name, device);
|
||||
}
|
||||
|
||||
state
|
||||
.shared_state
|
||||
.data_control_manager
|
||||
.set(manager)
|
||||
.expect("ext_data_control_manager_v1 already set, global appeared twice?");
|
||||
}
|
||||
}
|
||||
wayland_client::protocol::wl_registry::Event::GlobalRemove { name } => {
|
||||
// try to remove, if it's not a wl_seat it may not exist
|
||||
state
|
||||
.shared_state
|
||||
.data_control_devices
|
||||
.lock()
|
||||
.unwrap()
|
||||
.remove(&name);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Dispatch<ExtDataControlManagerV1, ()> for WlState {
|
||||
|
|
@ -93,6 +150,12 @@ impl Dispatch<WlSeat, ()> for WlState {
|
|||
}
|
||||
}
|
||||
impl Dispatch<ExtDataControlDeviceV1, ()> for WlState {
|
||||
#[tracing::instrument(
|
||||
skip(state, _proxy, event, _data, _conn, _qhandle),
|
||||
level = "info",
|
||||
ret,
|
||||
target = "ExtDataControlDeviceV1::event"
|
||||
)]
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_proxy: &ExtDataControlDeviceV1,
|
||||
|
|
@ -141,8 +204,8 @@ impl Dispatch<ExtDataControlDeviceV1, ()> for WlState {
|
|||
.iter()
|
||||
.find(|mime| offer.mime_types.contains(**mime))
|
||||
else {
|
||||
eprintln!(
|
||||
"WARN: No supported mime type found. Found mime types: {:?}",
|
||||
warn!(
|
||||
"No supported mime type found. Found mime types: {:?}",
|
||||
offer.mime_types
|
||||
);
|
||||
return;
|
||||
|
|
@ -151,14 +214,14 @@ impl Dispatch<ExtDataControlDeviceV1, ()> for WlState {
|
|||
let (reader, writer) = std::io::pipe().unwrap();
|
||||
offer.offer.receive(mime.to_string(), writer.as_fd());
|
||||
|
||||
let history_state = state.history_state.clone();
|
||||
let history_state = state.shared_state.clone();
|
||||
let mime = mime.to_string();
|
||||
let time = offer.time;
|
||||
std::thread::spawn(move || {
|
||||
let result =
|
||||
do_read_clipboard_into_history(&history_state, time, mime, reader);
|
||||
if let Err(err) = result {
|
||||
eprintln!("WARN: Failed to read clipboard: {:?}", err)
|
||||
warn!("Failed to read clipboard: {:?}", err)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -183,6 +246,9 @@ impl Dispatch<ExtDataControlDeviceV1, ()> for WlState {
|
|||
|
||||
state.current_primary_selection = new_offer;
|
||||
}
|
||||
ext_data_control_device_v1::Event::Finished => {
|
||||
warn!("device finished :(");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -212,7 +278,54 @@ impl Dispatch<ExtDataControlOfferV1, ()> for WlState {
|
|||
}
|
||||
}
|
||||
|
||||
impl Dispatch<ExtDataControlSourceV1, OfferData> for WlState {
|
||||
#[tracing::instrument(
|
||||
skip(_state, proxy, event, data, _conn, _qhandle),
|
||||
level = "info",
|
||||
ret,
|
||||
target = "ExtDataControlSourceV1::event"
|
||||
)]
|
||||
fn event(
|
||||
_state: &mut Self,
|
||||
proxy: &ExtDataControlSourceV1,
|
||||
event: <ExtDataControlSourceV1 as Proxy>::Event,
|
||||
data: &OfferData,
|
||||
_conn: &wayland_client::Connection,
|
||||
_qhandle: &QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
ext_data_control_source_v1::Event::Send { mime_type: _, fd } => {
|
||||
info!("pasting {:?}", std::str::from_utf8(&data.0));
|
||||
|
||||
let data = data.0.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let mut writer = BufWriter::new(PipeWriter::from(fd));
|
||||
|
||||
let result = writer.write_all(&data);
|
||||
if let Err(err) = result {
|
||||
warn!("Failed to write to requester: {:?}", err);
|
||||
}
|
||||
let result = writer.into_inner();
|
||||
if let Err(err) = result {
|
||||
warn!("Failed to write to requester: {:?}", err);
|
||||
}
|
||||
});
|
||||
}
|
||||
ext_data_control_source_v1::Event::Cancelled => {
|
||||
info!("We have been replaced.");
|
||||
proxy.destroy();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main(socket_path: &PathBuf) -> eyre::Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(EnvFilter::try_from_default_env().unwrap_or(EnvFilter::new("info")))
|
||||
.init();
|
||||
|
||||
let _ = std::fs::remove_file(&socket_path); // lol
|
||||
let socket = UnixListener::bind(&socket_path)
|
||||
.wrap_err_with(|| format!("binding path {}", socket_path.display()))?;
|
||||
|
|
@ -220,53 +333,70 @@ pub fn main(socket_path: &PathBuf) -> eyre::Result<()> {
|
|||
let conn =
|
||||
wayland_client::Connection::connect_to_env().wrap_err("connecting to the compositor")?;
|
||||
|
||||
let (globals, mut queue) =
|
||||
registry_queue_init::<WlState>(&conn).wrap_err("initializing wayland connection")?;
|
||||
let mut queue = conn.new_event_queue::<WlState>();
|
||||
|
||||
let data_manager = globals.bind::<ExtDataControlManagerV1, _, _>(&queue.handle(), 1..=1, ()).wrap_err("getting ext_data_control_manager_v1, is ext-data-control-v1 not supported by the compositor?")?;
|
||||
let shared_state = Arc::new(SharedState {
|
||||
next_item_id: AtomicU64::new(0),
|
||||
last_copied_item_id: AtomicU64::new(u64::MAX),
|
||||
items: Mutex::new(Vec::<HistoryItem>::new()),
|
||||
|
||||
let seat = globals
|
||||
.bind::<WlSeat, _, _>(&queue.handle(), 1..=1, ())
|
||||
.wrap_err("getting seat")?;
|
||||
|
||||
let data_device = data_manager.get_data_device(&seat, &queue.handle(), ());
|
||||
|
||||
let history_state = Arc::new(HistoryState {
|
||||
next_item_id: Arc::new(AtomicU64::new(0)),
|
||||
last_copied_item_id: Arc::new(AtomicU64::new(u64::MAX)),
|
||||
items: Arc::new(Mutex::new(Vec::<HistoryItem>::new())),
|
||||
// for deduplication because the event stream will tell us that we just copied something :)
|
||||
data_control_manager: OnceLock::new(),
|
||||
data_control_devices: Mutex::new(HashMap::new()),
|
||||
qh: queue.handle(),
|
||||
});
|
||||
|
||||
let history_state2 = history_state.clone();
|
||||
std::thread::spawn(move || {
|
||||
let mut state = WlState {
|
||||
offers: HashMap::new(),
|
||||
current_primary_selection: None,
|
||||
current_selection: None,
|
||||
let history_state2 = shared_state.clone();
|
||||
|
||||
history_state: history_state2,
|
||||
};
|
||||
let mut wl_state = WlState {
|
||||
offers: HashMap::new(),
|
||||
current_primary_selection: None,
|
||||
current_selection: None,
|
||||
deferred_seats: Vec::new(),
|
||||
|
||||
shared_state: history_state2,
|
||||
};
|
||||
|
||||
conn.display().get_registry(&queue.handle(), ());
|
||||
|
||||
queue
|
||||
.roundtrip(&mut wl_state)
|
||||
.wrap_err("failed to set up wayland state")?;
|
||||
|
||||
if wl_state.shared_state.data_control_manager.get().is_none() {
|
||||
bail!(
|
||||
"{} not found, the ext-data-control-v1 Wayland extension is likely unsupported by your compositor.\n\
|
||||
check https://wayland.app/protocols/ext-data-control-v1#compositor-support
|
||||
",
|
||||
ExtDataControlManagerV1::interface().name
|
||||
);
|
||||
}
|
||||
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
queue.blocking_dispatch(&mut state);
|
||||
let result = queue
|
||||
.blocking_dispatch(&mut wl_state)
|
||||
.wrap_err("handling wayland");
|
||||
if let Err(err) = result {
|
||||
warn!("Received error from Wayland: {:?}", err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
println!("INFO: Listening on {}", socket_path.display());
|
||||
info!("Listening on {}", socket_path.display());
|
||||
|
||||
for peer in socket.incoming() {
|
||||
match peer {
|
||||
Ok(peer) => {
|
||||
let history_state = history_state.clone();
|
||||
let history_state = shared_state.clone();
|
||||
std::thread::spawn(move || {
|
||||
let result = handle_peer(peer, &history_state);
|
||||
if let Err(err) = result {
|
||||
eprintln!("ERROR: Error handling peer: {err:?}");
|
||||
warn!("Error handling peer: {err:?}");
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("ERROR: Error accepting peer: {err}");
|
||||
warn!("Error accepting peer: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -274,91 +404,84 @@ pub fn main(socket_path: &PathBuf) -> eyre::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_peer(mut peer: UnixStream, history_state: &HistoryState) -> eyre::Result<()> {
|
||||
#[tracing::instrument(skip(peer, shared_state), level = "info")]
|
||||
fn handle_peer(mut peer: UnixStream, shared_state: &SharedState) -> eyre::Result<()> {
|
||||
let mut request = [0; 1];
|
||||
let Ok(()) = peer.read_exact(&mut request) else {
|
||||
return Ok(());
|
||||
};
|
||||
match request[0] {
|
||||
super::MESSAGE_STORE => {
|
||||
handle_store(history_state).wrap_err("handling store message")?;
|
||||
}
|
||||
super::MESSAGE_READ => {
|
||||
let items = history_state.items.lock().unwrap();
|
||||
let items = shared_state.items.lock().unwrap();
|
||||
|
||||
ciborium::into_writer(items.as_slice(), BufWriter::new(peer))
|
||||
.wrap_err("writing items to socket")?;
|
||||
}
|
||||
super::MESSAGE_COPY => {
|
||||
handle_copy(peer, history_state).wrap_err("handling copy message")?;
|
||||
handle_copy(peer, shared_state).wrap_err("handling copy message")?;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_copy(mut peer: UnixStream, history_state: &HistoryState) -> Result<(), eyre::Error> {
|
||||
struct OfferData(Arc<[u8]>);
|
||||
|
||||
fn handle_copy(mut peer: UnixStream, shared_state: &SharedState) -> Result<(), eyre::Error> {
|
||||
let mut id = [0; 8];
|
||||
peer.read_exact(&mut id).wrap_err("failed to read id")?;
|
||||
let id = u64::from_le_bytes(id);
|
||||
let mut items = history_state.items.lock().unwrap();
|
||||
let mut items = shared_state.items.lock().unwrap();
|
||||
let Some(idx) = items.iter().position(|item| item.id == id) else {
|
||||
return Ok(());
|
||||
};
|
||||
let entry = items.remove(idx);
|
||||
items.push(entry.clone());
|
||||
let mut opts = wl_clipboard_rs::copy::Options::new();
|
||||
opts.clipboard(wl_clipboard_rs::copy::ClipboardType::Regular)
|
||||
.seat(wl_clipboard_rs::copy::Seat::All);
|
||||
let result = wl_clipboard_rs::copy::copy(
|
||||
opts,
|
||||
wl_clipboard_rs::copy::Source::Bytes(entry.data.into_boxed_slice()),
|
||||
wl_clipboard_rs::copy::MimeType::Specific(entry.mime),
|
||||
);
|
||||
history_state
|
||||
|
||||
drop(items);
|
||||
|
||||
for device in &*shared_state.data_control_devices.lock().unwrap() {
|
||||
let data_source = shared_state
|
||||
.data_control_manager
|
||||
.get()
|
||||
.expect("data manger not found")
|
||||
.create_data_source(&shared_state.qh, OfferData(entry.data.clone()));
|
||||
|
||||
if entry.mime == "text/plain" {
|
||||
// Just like wl_clipboard_rs, we also offer some extra mimes for text.
|
||||
let text_mimes = [
|
||||
"text/plain;charset=utf-8",
|
||||
"text/plain",
|
||||
"STRING",
|
||||
"UTF8_STRING",
|
||||
"TEXT",
|
||||
];
|
||||
for mime in text_mimes {
|
||||
data_source.offer(mime.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
data_source.offer(entry.mime.clone());
|
||||
|
||||
info!("setting the selection");
|
||||
|
||||
device.1.set_selection(Some(&data_source));
|
||||
}
|
||||
|
||||
shared_state
|
||||
.last_copied_item_id
|
||||
.store(entry.id, std::sync::atomic::Ordering::Relaxed);
|
||||
if let Err(err) = result {
|
||||
println!("WARNING: Copy failed: {err:?}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_store(history_state: &HistoryState) -> Result<(), eyre::Error> {
|
||||
let time = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap();
|
||||
|
||||
let mime_types =
|
||||
wl_clipboard_rs::paste::get_mime_types(ClipboardType::Regular, Seat::Unspecified)
|
||||
.wrap_err("getting mime types")?;
|
||||
|
||||
let Some(mime) = ["text/plain", "image/png"]
|
||||
.iter()
|
||||
.find(|mime| mime_types.contains(**mime))
|
||||
else {
|
||||
eprintln!("WARN: No supported mime type found. Found mime types: {mime_types:?}");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let (data_readear, _) = wl_clipboard_rs::paste::get_contents(
|
||||
ClipboardType::Regular,
|
||||
Seat::Unspecified,
|
||||
MimeType::Specific(mime),
|
||||
)
|
||||
.wrap_err("getting contents")?;
|
||||
|
||||
do_read_clipboard_into_history(&history_state, time, mime.to_string(), data_readear)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_read_clipboard_into_history(
|
||||
history_state: &HistoryState,
|
||||
history_state: &SharedState,
|
||||
time: std::time::Duration,
|
||||
mime: String,
|
||||
data_reader: impl Read,
|
||||
) -> Result<(), eyre::Error> {
|
||||
let mut data_reader = data_reader.take(MAX_ENTRY_SIZE);
|
||||
let mut data_reader = BufReader::new(data_reader).take(MAX_ENTRY_SIZE);
|
||||
let mut data = Vec::new();
|
||||
data_reader
|
||||
.read_to_end(&mut data)
|
||||
|
|
@ -368,7 +491,7 @@ fn do_read_clipboard_into_history(
|
|||
.next_item_id
|
||||
.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
|
||||
mime: mime.to_string(),
|
||||
data,
|
||||
data: data.into(),
|
||||
created_time: u64::try_from(time.as_millis()).unwrap(),
|
||||
};
|
||||
let mut items = history_state.items.lock().unwrap();
|
||||
|
|
@ -376,7 +499,7 @@ fn do_read_clipboard_into_history(
|
|||
.last()
|
||||
.is_some_and(|last| last.mime == new_entry.mime && last.data == new_entry.data)
|
||||
{
|
||||
println!("INFO: Skipping store of new item because it is identical to last one");
|
||||
info!("INFO: Skipping store of new item because it is identical to last one");
|
||||
return Ok(());
|
||||
}
|
||||
let last_copied = history_state
|
||||
|
|
@ -386,7 +509,7 @@ fn do_read_clipboard_into_history(
|
|||
&& item.mime == new_entry.mime
|
||||
&& item.data == new_entry.data
|
||||
{
|
||||
println!("INFO: Skipping store of new item because the copy came from us");
|
||||
info!("Skipping store of new item because the copy came from us");
|
||||
return Ok(());
|
||||
}
|
||||
items.push(new_entry);
|
||||
|
|
@ -399,15 +522,15 @@ fn do_read_clipboard_into_history(
|
|||
}
|
||||
}
|
||||
if let Some(cutoff) = cutoff {
|
||||
println!(
|
||||
"INFO: Dropping old {} items because limit of {} bytes was reached for the history",
|
||||
info!(
|
||||
"Dropping old {} items because limit of {} bytes was reached for the history",
|
||||
cutoff + 1,
|
||||
crate::MAX_HISTORY_BYTE_SIZE
|
||||
);
|
||||
items.splice(0..=cutoff, []);
|
||||
}
|
||||
println!(
|
||||
"INFO: Successfully stored clipboard value of mime type {mime} (new history size {running_total})"
|
||||
info!(
|
||||
"Successfully stored clipboard value of mime type {mime} (new history size {running_total})"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
40
src/main.rs
40
src/main.rs
|
|
@ -1,8 +1,9 @@
|
|||
mod daemon;
|
||||
mod display;
|
||||
|
||||
use eyre::{Context, OptionExt, bail};
|
||||
use std::{io::Write, os::unix::net::UnixStream};
|
||||
use eyre::{OptionExt, bail};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::sync::Arc;
|
||||
|
||||
const MAX_ENTRY_SIZE: u64 = 50_000_000;
|
||||
const MAX_HISTORY_BYTE_SIZE: usize = 100_000_000;
|
||||
|
|
@ -11,11 +12,23 @@ const MAX_HISTORY_BYTE_SIZE: usize = 100_000_000;
|
|||
struct HistoryItem {
|
||||
id: u64,
|
||||
mime: String,
|
||||
data: Vec<u8>,
|
||||
#[serde(
|
||||
deserialize_with = "deserialize_data",
|
||||
serialize_with = "serialize_data"
|
||||
)]
|
||||
data: Arc<[u8]>,
|
||||
created_time: u64,
|
||||
}
|
||||
|
||||
const MESSAGE_STORE: u8 = 0;
|
||||
fn deserialize_data<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Arc<[u8]>, D::Error> {
|
||||
Box::<[u8]>::deserialize(deserializer).map(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_data<S: Serializer>(data: &Arc<[u8]>, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let data: &[u8] = data;
|
||||
data.serialize(serializer)
|
||||
}
|
||||
|
||||
const MESSAGE_READ: u8 = 1;
|
||||
/// Argument: One u64-bit LE value, the ID
|
||||
const MESSAGE_COPY: u8 = 2;
|
||||
|
|
@ -31,25 +44,8 @@ fn main() -> eyre::Result<()> {
|
|||
|
||||
match mode.as_str() {
|
||||
"daemon" => daemon::main(&socket_path)?,
|
||||
"store" => {
|
||||
let mut socket = UnixStream::connect(&socket_path).wrap_err_with(|| {
|
||||
format!(
|
||||
"connecting to socket at {}. is the daemon running?",
|
||||
socket_path.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
if std::env::args().any(|arg| arg == "--wl-copy") {
|
||||
std::io::copy(&mut std::io::stdin(), &mut std::io::empty())
|
||||
.wrap_err("reading stdin in --wl-copy mode")?;
|
||||
}
|
||||
|
||||
socket
|
||||
.write_all(&[MESSAGE_STORE])
|
||||
.wrap_err("writing request type")?;
|
||||
}
|
||||
"display" => display::main(&socket_path)?,
|
||||
_ => panic!("invalid mode"),
|
||||
_ => panic!("invalid mode, supported: daemon, display"),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue