From 35f01cafe3df0eec2e59f7d829fca216b7f9d6ea Mon Sep 17 00:00:00 2001 From: Armin Friedl Date: Thu, 14 Oct 2021 21:29:16 +0200 Subject: [PATCH] Unstable winit, matcher, xcb fix - Move to unstable winit since 0.25.0 does not handle transparency correctly on X11 - Matcher trait to enable different matching algorithms - Find correct visualtype for cairo xcb surface: Visualtype was more or less taken randomly which only worked by chance. Now find visualtype that corresponds to visualid of the winit window which should be the correct one. --- Cargo.lock | 377 ++++++++++++++---------------------------- Cargo.toml | 6 +- src/main.rs | 97 ++++++++--- src/matcher/mod.rs | 5 + src/matcher/prefix.rs | 22 +++ src/matcher/skim.rs | 24 +++ src/roftl.rs | 55 ++++-- src/sources/mod.rs | 1 - src/ui.rs | 69 ++++++-- 9 files changed, 345 insertions(+), 311 deletions(-) create mode 100644 src/matcher/mod.rs create mode 100644 src/matcher/prefix.rs create mode 100644 src/matcher/skim.rs diff --git a/Cargo.lock b/Cargo.lock index fd3a1f8..82845e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fe5e32de01730eb1f6b7f5b51c17e03e2325bf40a74f754f04f130043affff" - [[package]] name = "aho-corasick" version = "0.7.18" @@ -17,37 +11,12 @@ dependencies = [ "memchr", ] -[[package]] -name = "andrew" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4afb09dd642feec8408e33f92f3ffc4052946f6b20f32fb99c1f58cd4fa7cf" -dependencies = [ - "bitflags", - "rusttype", - "walkdir", - "xdg", - "xml-rs", -] - [[package]] name = "anyhow" version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "atty" version = "0.2.14" @@ -65,35 +34,24 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "blake2b_simd" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - [[package]] name = "block" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "bumpalo" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538" + [[package]] name = "cairo-rs" version = "0.14.7" @@ -120,12 +78,12 @@ dependencies = [ [[package]] name = "calloop" -version = "0.6.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b036167e76041694579972c28cf4877b4f92da222560ddb49008937b6a6727c" +checksum = "42dcfbd723aa6eff9f024cfd5ad08b11144d79b2d8d37b4a31a006ceab255c77" dependencies = [ "log", - "nix 0.18.0", + "nix", ] [[package]] @@ -186,12 +144,6 @@ dependencies = [ "objc", ] -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "core-foundation" version = "0.7.0" @@ -274,20 +226,6 @@ dependencies = [ "objc", ] -[[package]] -name = "crossbeam" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - [[package]] name = "crossbeam-channel" version = "0.5.1" @@ -322,16 +260,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "crossbeam-queue" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.5" @@ -388,39 +316,19 @@ dependencies = [ "syn", ] -[[package]] -name = "dirs" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dispatch" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" -[[package]] -name = "dlib" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76" -dependencies = [ - "libloading 0.6.7", -] - [[package]] name = "dlib" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" dependencies = [ - "libloading 0.7.1", + "libloading", ] [[package]] @@ -516,14 +424,12 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.1.16" +name = "fuzzy-matcher" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi", + "thread_local", ] [[package]] @@ -618,6 +524,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" dependencies = [ "cfg-if 1.0.0", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -635,6 +544,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "js-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -647,16 +565,6 @@ version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" -[[package]] -name = "libloading" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] - [[package]] name = "libloading" version = "0.7.1" @@ -702,9 +610,9 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memmap2" -version = "0.1.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" +checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357" dependencies = [ "libc", ] @@ -737,18 +645,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "mio-misc" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ddf05411bb159cdb5801bb10002afb66cb4572be656044315e363460ce69dc2" -dependencies = [ - "crossbeam", - "crossbeam-queue", - "log", - "mio", -] - [[package]] name = "miow" version = "0.3.7" @@ -805,26 +701,15 @@ checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" [[package]] name = "nix" -version = "0.18.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" -dependencies = [ - "bitflags", - "cc", - "cfg-if 0.1.10", - "libc", -] - -[[package]] -name = "nix" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +checksum = "cf1e25ee6b412c2a1e3fcb6a4499a5c1bfe7f43e014bdce9a6b6666e5aa2d187" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", + "memoffset", ] [[package]] @@ -894,15 +779,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" -[[package]] -name = "owned_ttf_parser" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" -dependencies = [ - "ttf-parser", -] - [[package]] name = "parking_lot" version = "0.11.2" @@ -923,7 +799,7 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.10", + "redox_syscall", "smallvec", "winapi", ] @@ -1047,12 +923,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.2.10" @@ -1062,17 +932,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "redox_users" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" -dependencies = [ - "getrandom", - "redox_syscall 0.1.57", - "rust-argon2", -] - [[package]] name = "regex" version = "1.5.4" @@ -1097,6 +956,7 @@ dependencies = [ "cairo-rs", "cairo-sys-rs", "env_logger", + "fuzzy-matcher", "log", "rayon", "winit", @@ -1104,37 +964,6 @@ dependencies = [ "xcb-util", ] -[[package]] -name = "rust-argon2" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" -dependencies = [ - "base64", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils", -] - -[[package]] -name = "rusttype" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "scoped-tls" version = "1.0.0" @@ -1167,18 +996,18 @@ checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "smithay-client-toolkit" -version = "0.12.3" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4750c76fd5d3ac95fa3ed80fe667d6a3d8590a960e5b575b98eea93339a80b80" +checksum = "8f41633cd89f7d598d5d933fe36ce614fe9eb54d8b5bc2340556d8b0b7f2c144" dependencies = [ - "andrew", "bitflags", "calloop", - "dlib 0.4.2", + "dlib", "lazy_static", "log", "memmap2", - "nix 0.18.0", + "nix", + "pkg-config", "wayland-client", "wayland-cursor", "wayland-protocols", @@ -1266,6 +1095,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +dependencies = [ + "once_cell", +] + [[package]] name = "toml" version = "0.5.8" @@ -1275,12 +1113,6 @@ dependencies = [ "serde", ] -[[package]] -name = "ttf-parser" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" - [[package]] name = "unicode-segmentation" version = "1.8.0" @@ -1306,32 +1138,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] -name = "walkdir" -version = "2.3.2" +name = "wasm-bindgen" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ - "same-file", - "winapi", - "winapi-util", + "cfg-if 1.0.0", + "wasm-bindgen-macro", ] [[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +name = "wasm-bindgen-backend" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" [[package]] name = "wayland-client" -version = "0.28.6" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ab332350e502f159382201394a78e3cc12d0f04db863429260164ea40e0355" +checksum = "6deeba72b1fd9e9fc6641603bd5f72fa465857e3577b9a823fc316ffd45e69b4" dependencies = [ "bitflags", "downcast-rs", "libc", - "nix 0.20.0", + "nix", "scoped-tls", "wayland-commons", "wayland-scanner", @@ -1340,11 +1209,11 @@ dependencies = [ [[package]] name = "wayland-commons" -version = "0.28.6" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21817947c7011bbd0a27e11b17b337bfd022e8544b071a2641232047966fbda" +checksum = "93d6377fc0efc620da05cb78c5dc846420940e7b2c471aa2faf59c58e063c2b7" dependencies = [ - "nix 0.20.0", + "nix", "once_cell", "smallvec", "wayland-sys", @@ -1352,20 +1221,20 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.28.6" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be610084edd1586d45e7bdd275fe345c7c1873598caa464c4fb835dee70fa65a" +checksum = "bf9197a26e00b5e282b57ea9b620e4305ea5682f55f0b1ad862e388abf2d2bb5" dependencies = [ - "nix 0.20.0", + "nix", "wayland-client", "xcursor", ] [[package]] name = "wayland-protocols" -version = "0.28.6" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "286620ea4d803bacf61fa087a4242ee316693099ee5a140796aaba02b29f861f" +checksum = "503643f261c0f18124a4666b8c1e66258cf68b51f675d6e64469fbc72ddf0cd6" dependencies = [ "bitflags", "wayland-client", @@ -1375,9 +1244,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.28.6" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce923eb2deb61de332d1f356ec7b6bf37094dc5573952e1c8936db03b54c03f1" +checksum = "7d3d043a8926b2836749018bfb393e2328cac86bd414b9c3d3f8c523d0dee2dd" dependencies = [ "proc-macro2", "quote", @@ -1386,15 +1255,25 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.28.6" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d841fca9aed7febf9bed2e9796c49bf58d4152ceda8ac949ebe00868d8f0feb8" +checksum = "fef2a7d20f93be1379a2dfd9457c291e840b942fa38fe0b95ad6b0425a22d43a" dependencies = [ - "dlib 0.5.0", + "dlib", "lazy_static", "pkg-config", ] +[[package]] +name = "web-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1429,10 +1308,10 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winit" version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79610794594d5e86be473ef7763f604f2159cbac8c94debd00df8fb41e86c2f8" +source = "git+https://github.com/rust-windowing/winit#1b3b82a3c1369c5248a2e6a251230ba6c615e918" dependencies = [ "bitflags", + "block", "cocoa", "core-foundation 0.9.1", "core-graphics 0.22.2", @@ -1443,7 +1322,6 @@ dependencies = [ "libc", "log", "mio", - "mio-misc", "ndk", "ndk-glue", "ndk-sys", @@ -1451,9 +1329,11 @@ dependencies = [ "parking_lot", "percent-encoding", "raw-window-handle", - "scopeguard", "smithay-client-toolkit", + "wasm-bindgen", "wayland-client", + "wayland-protocols", + "web-sys", "winapi", "x11-dl", ] @@ -1498,15 +1378,6 @@ dependencies = [ "nom", ] -[[package]] -name = "xdg" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de4cfc7dc9727713f386aadce9496f1ed64ea368d9f1f813a54d0f98f8741286" -dependencies = [ - "dirs", -] - [[package]] name = "xml-rs" version = "0.8.4" diff --git a/Cargo.toml b/Cargo.toml index 2985946..07a6a67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,10 @@ log = "0.4" env_logger = "0.9.0" rayon = "1.5.1" -winit = "0.25" +winit = {git="https://github.com/rust-windowing/winit"} cairo-rs = {version = "0.14.0", features = ["xcb"]} cairo-sys-rs = {version = "0.14.0", features = ["xcb"]} xcb = "0.9.0" -xcb-util = {version = "0.3.0", features = ["ewmh", "icccm"]} \ No newline at end of file +xcb-util = {version = "0.3.0", features = ["ewmh", "icccm"]} + +fuzzy-matcher = "0.3.7" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 382223d..f77530d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,56 +1,77 @@ use log::{debug, trace}; use std::error::Error; -use winit::{event::{Event, WindowEvent::{CloseRequested, ReceivedCharacter}}, event_loop::{ControlFlow, EventLoop}, window::{Window, WindowBuilder}}; +use winit::window::{Window, WindowBuilder}; +use winit::event_loop::{ControlFlow, EventLoop}; +use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, + WindowEvent::{CloseRequested, ReceivedCharacter}}; + +use crate::matcher::SkimMatcher; mod roftl; mod ui; mod sources; +mod matcher; fn main() -> Result<(), Box> { env_logger::init(); debug!{"Set up roftl"}; - let roftl = roftl::Roftl::default() + let mut roftl = roftl::Roftl::new() .add_source(sources::TestSource::new("ts1")) - .add_source(sources::Window::new()); + .add_source(sources::Window::new()) + .with_matcher(SkimMatcher::new()); debug!{"Source roftl sources"} roftl.source(); - let mut input_buffer = String::new(); - debug!{"Build window"} let event_loop = EventLoop::new(); let window = WindowBuilder::new() + .with_decorations(false) .with_transparent(true) .build(&event_loop) .expect("Could not create window"); + debug!{"Window id: {:?}", window.id()} + debug!{"Draw empty state to window"} - ui::draw_on_window(&window, ""); + ui::draw_on_window(&window, "", vec![]); + + let mut input_buffer = String::new(); debug!{"Start event loop"} event_loop.run(move |evt, _win, flow| { *flow = ControlFlow::Wait; - if let Event::WindowEvent{window_id, ..} = evt { - if window_id != window.id() { - debug!{"Received event for foreign window"} - return; - } - } - match evt { - Event::WindowEvent{event: CloseRequested, ..} => *flow = ControlFlow::Exit, - - Event::WindowEvent{event: ReceivedCharacter(character), ..} => { - *flow = process_input(character, &mut input_buffer, &window) + Event::WindowEvent{event: CloseRequested, window_id} + if window_id == window.id() => + { + *flow = ControlFlow::Exit; } - Event::RedrawRequested(window_id) if window_id == window.id() => { + Event::WindowEvent{event: ReceivedCharacter(character), window_id} + if window_id == window.id() => + { + *flow = process_character(character, &mut input_buffer, &window); + } + + Event::WindowEvent{event: winit::event::WindowEvent::KeyboardInput{input, ..}, window_id} + if window_id == window.id() => + { + process_input(input, &mut input_buffer, &window); + } + + Event::RedrawRequested(window_id) + if window_id == window.id() => + { trace!{"Redrawing with input {}", input_buffer} - ui::draw_on_window(&window, &input_buffer); + + let result = roftl.narrow(&input_buffer); + trace!{"Narrow result {:?}", result} + + ui::draw_on_window(&window, &input_buffer, result); } _ => () @@ -58,12 +79,32 @@ fn main() -> Result<(), Box> { }); } -fn process_input(character: char, input_buffer: &mut String, window: &Window) -> ControlFlow { +fn process_input(input: KeyboardInput, input_buffer: &mut String, window: &Window) -> ControlFlow { + if let KeyboardInput { virtual_keycode: Some(code), state, .. } = input { + return match (code, state) { + (VirtualKeyCode::Down, ElementState::Released) => { + debug!("Received down"); + ControlFlow::Wait + }, + (VirtualKeyCode::Up, ElementState::Released) => { + debug!("Received up"); + ControlFlow::Wait + }, + + _ => ControlFlow::Wait, + } + } + + ControlFlow::Wait +} + + +fn process_character(character: char, input_buffer: &mut String, window: &Window) -> ControlFlow { match character { 'q' | 'Q' => ControlFlow::Exit, // Escape - c if c == char::from(0x1b) => ControlFlow::Exit, + c if c == char::from(0x1b) => ControlFlow::Exit, // Backspace c if c == char::from(0x08) => { @@ -73,8 +114,20 @@ fn process_input(character: char, input_buffer: &mut String, window: &Window) -> ControlFlow::Wait } + // Ctrl+n + c if c == char::from(0x0e) => { + debug!{"Received Ctrl+next"} + ControlFlow::Wait + } + + // Ctrl+p + c if c == char::from(0x10) => { + debug!{"Received Ctrl+previous"} + ControlFlow::Wait + } + c if c.is_control() => { - debug!{"Got unknown control character"} + debug!{"Got unknown control character {:#x}", u32::from(c)} ControlFlow::Wait } diff --git a/src/matcher/mod.rs b/src/matcher/mod.rs new file mode 100644 index 0000000..be98d1c --- /dev/null +++ b/src/matcher/mod.rs @@ -0,0 +1,5 @@ +mod prefix; +pub use prefix::PrefixMatcher; + +mod skim; +pub use skim::SkimMatcher; diff --git a/src/matcher/prefix.rs b/src/matcher/prefix.rs new file mode 100644 index 0000000..29e438c --- /dev/null +++ b/src/matcher/prefix.rs @@ -0,0 +1,22 @@ +use crate::roftl::Matcher; + +pub struct PrefixMatcher; + +impl PrefixMatcher { + pub fn new() -> Box { + Box::new(PrefixMatcher{}) + } +} + +impl Matcher for PrefixMatcher { + fn try_match(&self, haystack: &str, needle: &str) -> Option<(f64, Vec)> { + let mut indices = vec![]; + + if haystack.starts_with(needle) { + (0..needle.len()).for_each(|i| indices.push(i)); + return Option::Some((1.0, indices)); + } + + Option::None + } +} diff --git a/src/matcher/skim.rs b/src/matcher/skim.rs new file mode 100644 index 0000000..409a2cf --- /dev/null +++ b/src/matcher/skim.rs @@ -0,0 +1,24 @@ +use fuzzy_matcher::{FuzzyMatcher, skim::SkimMatcherV2}; + +use crate::roftl::Matcher; + +pub struct SkimMatcher { + matcher: SkimMatcherV2 +} + +impl SkimMatcher { + pub fn new() -> Box { + Box::new(SkimMatcher{ + matcher: SkimMatcherV2::default() + }) + } +} + +impl Matcher for SkimMatcher { + fn try_match(&self, haystack: &str, needle: &str) -> Option<(f64, Vec)> { + match self.matcher.fuzzy_indices(haystack, needle) { + Some((score, indices)) => Some(((i64::MAX as f64/score as f64), indices)), + None => None + } + } +} diff --git a/src/roftl.rs b/src/roftl.rs index c9fc517..e84ef9c 100644 --- a/src/roftl.rs +++ b/src/roftl.rs @@ -1,7 +1,12 @@ -use std::{collections::HashMap, sync::Mutex}; +use std::{collections::HashMap, sync::{Arc, Mutex, atomic::{AtomicUsize, Ordering}}}; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator}; +use super::matcher::PrefixMatcher; + +pub type SourceRef = Box; +pub type MatcherRef = Box; + #[derive(Clone, Debug)] pub struct Entry { pub source: &'static str, @@ -21,45 +26,61 @@ pub trait Source: Send + Sync { fn action(&self, entry: &Entry, action: Action); } -#[derive(Default)] +pub trait Matcher: Send + Sync { + fn try_match(&self, haystack: &str, needle: &str) -> Option<(f64, Vec)>; +} + pub struct Roftl { - sources: Vec>, + sources: Vec, + matcher: MatcherRef, entries: Vec, narrow_map: Mutex> } impl Roftl { - pub fn add_source(mut self, source: Box) -> Self { + pub fn new() -> Self { + Roftl { + sources: vec![], + matcher: PrefixMatcher::new(), + entries: vec![], + narrow_map: Mutex::default() + } + } + + pub fn add_source(mut self, source: SourceRef) -> Self { if self.sources.par_iter().any(|s| s.name().eq(source.name())) { - panic! {"Source with name '{}' already exists", source.name()} + panic! {"Source with name '{}' already exists", source.name()} } self.sources.push(source); self } - pub fn source(mut self) -> Self { - self.entries = self - .sources - .par_iter_mut() - .flat_map_iter(|s| s.entries()) - .collect(); - - println!("Entries {:?}", self.entries); + pub fn with_matcher(mut self, matcher: MatcherRef) -> Self { + self.matcher = matcher; self } + pub fn source(&mut self) { + self.entries = self + .sources + .par_iter_mut() + .flat_map(|s| s.entries()) + .collect(); + + println!("Entries {:?}", self.entries); + } + pub fn narrow(&self, input: &str) -> Vec<&Entry> { - let count = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0)); + let count = Arc::new(AtomicUsize::new(0)); self.narrow_map.lock().unwrap().clear(); self.entries .par_iter() .enumerate() - .filter(|(_idx, e)| e.name.starts_with(input)) + .filter(|(_idx, e)| self.matcher.try_match(&e.name, input).is_some()) .map(move |(idx, e)| { - self.narrow_map.lock().unwrap().insert(count.load(std::sync::atomic::Ordering::Acquire), idx); - count.fetch_add(1, std::sync::atomic::Ordering::Acquire); + self.narrow_map.lock().unwrap().insert(count.fetch_add(1, Ordering::Relaxed), idx); e }) .collect() diff --git a/src/sources/mod.rs b/src/sources/mod.rs index ee10e2f..314ddc8 100644 --- a/src/sources/mod.rs +++ b/src/sources/mod.rs @@ -3,4 +3,3 @@ pub use test::TestSource; mod windows; pub use windows::Window; - diff --git a/src/ui.rs b/src/ui.rs index 894e0b4..611b8e9 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,34 +1,52 @@ -use std::{borrow::BorrowMut, ffi::c_void}; +use std::borrow::BorrowMut; +use std::ffi::c_void; +use log::debug; use winit::{platform::unix::WindowExtUnix, window::Window}; +use super::roftl::Entry; -fn get_visual_type(mut connection: T) -> xcb::Visualtype +fn get_visual_type(mut connection: T, window_id: u32) -> xcb::Visualtype where T: BorrowMut<*mut c_void> { let xcb_conn = unsafe { xcb::Connection::from_raw_conn(*connection.borrow_mut() as *mut xcb::ffi::xcb_connection_t) }; - let setup = xcb_conn.get_setup(); - let mut roots = setup.roots(); - let screen = roots.next().unwrap(); - let depth = screen.allowed_depths().next().unwrap(); - let visualtype = depth.visuals().next().unwrap(); + let window_visualid = xcb::get_window_attributes(&xcb_conn, window_id) + .get_reply() + .expect("Could not fetch attributes for window") + .visual(); + + debug!{"Found visualid {} for window", window_visualid} + + debug!{"Trying to map visualid to visualtype {}", window_visualid} + let visualtype = xcb_conn.get_setup().roots() + .flat_map(|screen| screen.allowed_depths()) + .flat_map(|depth| depth.visuals()) + .find(|visualtype| {visualtype.visual_id() == window_visualid}) + .expect("Could not match visualid to visualtype"); // xcb::Connection calls disconnect on the underlying xcb_connection_t // when dropped. We cannot let this happen since the xcb_connection_t // is actually owned by the winit::Window + // We try to signify this with `where T: BorrowMut<*mut c_void>` but + // this is unfortunately not enforced down to the raw pointer std::mem::forget(xcb_conn); visualtype } -fn make_context(window: &Window) -> cairo::Context { +fn make_context(window: &Window) -> cairo::Context +{ let winit_xcb_conn = window .xcb_connection() .expect("Could not get connection from window"); + let xlib_window_id = window + .xlib_window() + .expect("Could not get xlib window"); + let visual_type = unsafe { - let mut visual_type = get_visual_type(winit_xcb_conn).base; + let mut visual_type = get_visual_type(winit_xcb_conn, xlib_window_id as u32).base; cairo::XCBVisualType::from_raw_none( &mut visual_type as *mut xcb::ffi::xcb_visualtype_t as *mut cairo::ffi::xcb_visualtype_t ) @@ -51,7 +69,8 @@ fn make_context(window: &Window) -> cairo::Context { cairo::Context::new(&surface).expect("Could not create drawing context") } -fn draw_rectangle(cr: &cairo::Context, x: f64, y: f64, width: f64, height: f64, aspect: f64) { +fn draw_rectangle(cr: &cairo::Context, x: f64, y: f64, width: f64, height: f64, aspect: f64) +{ let corner_radius = height / 10.0; /* and corner curvature radius */ let radius = corner_radius / aspect; let degrees = std::f64::consts::PI / 180.0; @@ -71,7 +90,8 @@ fn draw_rectangle(cr: &cairo::Context, x: f64, y: f64, width: f64, height: f64, cr.stroke ().unwrap(); } -fn draw_text(cr: &cairo::Context, input: &str) { +fn draw_text(cr: &cairo::Context, input: &str) +{ cr.select_font_face ("serif", cairo::FontSlant::Normal, cairo::FontWeight::Normal); cr.set_font_size (0.25); cr.set_source_rgb (0.0, 0.0, 1.0); @@ -87,9 +107,25 @@ fn draw_text(cr: &cairo::Context, input: &str) { } } -pub fn draw_on_window(window: &Window, input: &str) { +fn draw_result(cr: &cairo::Context, input: &str, x: f64, y: f64) +{ + cr.select_font_face ("serif", cairo::FontSlant::Normal, cairo::FontWeight::Normal); + cr.set_font_size (0.25); + cr.set_source_rgb (0.0, 0.0, 1.0); + cr.move_to (x, y); + cr.show_text(input).unwrap(); +} + +pub fn draw_on_window(window: &Window, input: &str, result: Vec<&Entry>) +{ let cr = make_context(&window); + cr.save().unwrap(); + cr.set_source_rgba(0.0, 0.0, 0.0, 0.5); + cr.set_operator(cairo::Operator::Source); + cr.paint().unwrap(); + cr.restore().unwrap(); + cr.translate(300.0, 300.0); cr.scale(100.0, 100.0); @@ -97,10 +133,11 @@ pub fn draw_on_window(window: &Window, input: &str) { draw_rectangle(&cr, 0.0, 0.0, 4.0, 0.3, 2.0); draw_text(&cr, input); - for i in 1..10 { - draw_rectangle(&cr, 0.0, 0.3*(i as f64), 4.0, 0.3, 2.0); - } - + result.iter().enumerate() + .for_each(|(i, e)| { + draw_rectangle(&cr, 0.0, 0.3*((1+i) as f64), 4.0, 0.3, 2.0); + draw_result(&cr, &e.name, 0.05, 0.3*((i+1) as f64)+0.23); + }); // cr.set_line_width(0.5); // cr.set_source_rgb(255.0, 255.0, 255.0);