├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── app.rs ├── environment.rs └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.toml 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adler" 7 | version = "1.0.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 10 | 11 | [[package]] 12 | name = "adler32" 13 | version = "1.2.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" 16 | 17 | [[package]] 18 | name = "ahash" 19 | version = "0.4.7" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" 22 | 23 | [[package]] 24 | name = "autocfg" 25 | version = "1.0.1" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 28 | 29 | [[package]] 30 | name = "bitflags" 31 | version = "1.2.1" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 34 | 35 | [[package]] 36 | name = "bytemuck" 37 | version = "1.7.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "9966d2ab714d0f785dbac0a0396251a35280aeb42413281617d0209ab4898435" 40 | 41 | [[package]] 42 | name = "byteorder" 43 | version = "1.4.3" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 46 | 47 | [[package]] 48 | name = "calloop" 49 | version = "0.7.2" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "9d0a1340115d6bd81e1066469091596a339f68878a2ce3c2f39e546607d22131" 52 | dependencies = [ 53 | "log", 54 | "nix 0.19.1", 55 | ] 56 | 57 | [[package]] 58 | name = "cc" 59 | version = "1.0.68" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" 62 | 63 | [[package]] 64 | name = "cfg-if" 65 | version = "1.0.0" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 68 | 69 | [[package]] 70 | name = "color_quant" 71 | version = "1.1.0" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" 74 | 75 | [[package]] 76 | name = "crc32fast" 77 | version = "1.2.1" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" 80 | dependencies = [ 81 | "cfg-if", 82 | ] 83 | 84 | [[package]] 85 | name = "crossbeam-channel" 86 | version = "0.5.1" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" 89 | dependencies = [ 90 | "cfg-if", 91 | "crossbeam-utils", 92 | ] 93 | 94 | [[package]] 95 | name = "crossbeam-deque" 96 | version = "0.8.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" 99 | dependencies = [ 100 | "cfg-if", 101 | "crossbeam-epoch", 102 | "crossbeam-utils", 103 | ] 104 | 105 | [[package]] 106 | name = "crossbeam-epoch" 107 | version = "0.9.5" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" 110 | dependencies = [ 111 | "cfg-if", 112 | "crossbeam-utils", 113 | "lazy_static", 114 | "memoffset", 115 | "scopeguard", 116 | ] 117 | 118 | [[package]] 119 | name = "crossbeam-utils" 120 | version = "0.8.5" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" 123 | dependencies = [ 124 | "cfg-if", 125 | "lazy_static", 126 | ] 127 | 128 | [[package]] 129 | name = "deflate" 130 | version = "0.8.6" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" 133 | dependencies = [ 134 | "adler32", 135 | "byteorder", 136 | ] 137 | 138 | [[package]] 139 | name = "dlib" 140 | version = "0.5.0" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" 143 | dependencies = [ 144 | "libloading", 145 | ] 146 | 147 | [[package]] 148 | name = "downcast-rs" 149 | version = "1.2.0" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" 152 | 153 | [[package]] 154 | name = "either" 155 | version = "1.6.1" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 158 | 159 | [[package]] 160 | name = "fontdue" 161 | version = "0.5.2" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "c75712fff1702bac51b7eaa5a5ca9f9853b8055ef5906088a32f4fe196595a1d" 164 | dependencies = [ 165 | "hashbrown", 166 | "ttf-parser", 167 | ] 168 | 169 | [[package]] 170 | name = "getrandom" 171 | version = "0.2.3" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 174 | dependencies = [ 175 | "cfg-if", 176 | "libc", 177 | "wasi", 178 | ] 179 | 180 | [[package]] 181 | name = "gif" 182 | version = "0.11.2" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "5a668f699973d0f573d15749b7002a9ac9e1f9c6b220e7b165601334c173d8de" 185 | dependencies = [ 186 | "color_quant", 187 | "weezl", 188 | ] 189 | 190 | [[package]] 191 | name = "hashbrown" 192 | version = "0.9.1" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" 195 | dependencies = [ 196 | "ahash", 197 | ] 198 | 199 | [[package]] 200 | name = "hermit-abi" 201 | version = "0.1.19" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 204 | dependencies = [ 205 | "libc", 206 | ] 207 | 208 | [[package]] 209 | name = "image" 210 | version = "0.23.14" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" 213 | dependencies = [ 214 | "bytemuck", 215 | "byteorder", 216 | "color_quant", 217 | "gif", 218 | "jpeg-decoder", 219 | "num-iter", 220 | "num-rational", 221 | "num-traits", 222 | "png", 223 | "scoped_threadpool", 224 | "tiff", 225 | ] 226 | 227 | [[package]] 228 | name = "jpeg-decoder" 229 | version = "0.1.22" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" 232 | dependencies = [ 233 | "rayon", 234 | ] 235 | 236 | [[package]] 237 | name = "lazy_static" 238 | version = "1.4.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 241 | 242 | [[package]] 243 | name = "libc" 244 | version = "0.2.98" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" 247 | 248 | [[package]] 249 | name = "libloading" 250 | version = "0.7.0" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" 253 | dependencies = [ 254 | "cfg-if", 255 | "winapi", 256 | ] 257 | 258 | [[package]] 259 | name = "log" 260 | version = "0.4.14" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 263 | dependencies = [ 264 | "cfg-if", 265 | ] 266 | 267 | [[package]] 268 | name = "memchr" 269 | version = "2.3.4" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" 272 | 273 | [[package]] 274 | name = "memmap2" 275 | version = "0.2.3" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4" 278 | dependencies = [ 279 | "libc", 280 | ] 281 | 282 | [[package]] 283 | name = "memoffset" 284 | version = "0.6.4" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" 287 | dependencies = [ 288 | "autocfg", 289 | ] 290 | 291 | [[package]] 292 | name = "miniz_oxide" 293 | version = "0.3.7" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" 296 | dependencies = [ 297 | "adler32", 298 | ] 299 | 300 | [[package]] 301 | name = "miniz_oxide" 302 | version = "0.4.4" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" 305 | dependencies = [ 306 | "adler", 307 | "autocfg", 308 | ] 309 | 310 | [[package]] 311 | name = "nix" 312 | version = "0.19.1" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" 315 | dependencies = [ 316 | "bitflags", 317 | "cc", 318 | "cfg-if", 319 | "libc", 320 | ] 321 | 322 | [[package]] 323 | name = "nix" 324 | version = "0.20.0" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" 327 | dependencies = [ 328 | "bitflags", 329 | "cc", 330 | "cfg-if", 331 | "libc", 332 | ] 333 | 334 | [[package]] 335 | name = "nom" 336 | version = "6.2.1" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6" 339 | dependencies = [ 340 | "memchr", 341 | "version_check", 342 | ] 343 | 344 | [[package]] 345 | name = "num-integer" 346 | version = "0.1.44" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 349 | dependencies = [ 350 | "autocfg", 351 | "num-traits", 352 | ] 353 | 354 | [[package]] 355 | name = "num-iter" 356 | version = "0.1.42" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" 359 | dependencies = [ 360 | "autocfg", 361 | "num-integer", 362 | "num-traits", 363 | ] 364 | 365 | [[package]] 366 | name = "num-rational" 367 | version = "0.3.2" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" 370 | dependencies = [ 371 | "autocfg", 372 | "num-integer", 373 | "num-traits", 374 | ] 375 | 376 | [[package]] 377 | name = "num-traits" 378 | version = "0.2.14" 379 | source = "registry+https://github.com/rust-lang/crates.io-index" 380 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 381 | dependencies = [ 382 | "autocfg", 383 | ] 384 | 385 | [[package]] 386 | name = "num_cpus" 387 | version = "1.13.0" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 390 | dependencies = [ 391 | "hermit-abi", 392 | "libc", 393 | ] 394 | 395 | [[package]] 396 | name = "once_cell" 397 | version = "1.8.0" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" 400 | 401 | [[package]] 402 | name = "paper" 403 | version = "0.1.0" 404 | dependencies = [ 405 | "rand", 406 | "smithay-client-toolkit", 407 | "snui", 408 | "wayland-client", 409 | "wayland-commons", 410 | "wayland-protocols", 411 | ] 412 | 413 | [[package]] 414 | name = "pkg-config" 415 | version = "0.3.19" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" 418 | 419 | [[package]] 420 | name = "png" 421 | version = "0.16.8" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" 424 | dependencies = [ 425 | "bitflags", 426 | "crc32fast", 427 | "deflate", 428 | "miniz_oxide 0.3.7", 429 | ] 430 | 431 | [[package]] 432 | name = "ppv-lite86" 433 | version = "0.2.10" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 436 | 437 | [[package]] 438 | name = "proc-macro2" 439 | version = "1.0.27" 440 | source = "registry+https://github.com/rust-lang/crates.io-index" 441 | checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" 442 | dependencies = [ 443 | "unicode-xid", 444 | ] 445 | 446 | [[package]] 447 | name = "quote" 448 | version = "1.0.9" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" 451 | dependencies = [ 452 | "proc-macro2", 453 | ] 454 | 455 | [[package]] 456 | name = "rand" 457 | version = "0.8.4" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" 460 | dependencies = [ 461 | "libc", 462 | "rand_chacha", 463 | "rand_core", 464 | "rand_hc", 465 | ] 466 | 467 | [[package]] 468 | name = "rand_chacha" 469 | version = "0.3.1" 470 | source = "registry+https://github.com/rust-lang/crates.io-index" 471 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 472 | dependencies = [ 473 | "ppv-lite86", 474 | "rand_core", 475 | ] 476 | 477 | [[package]] 478 | name = "rand_core" 479 | version = "0.6.3" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 482 | dependencies = [ 483 | "getrandom", 484 | ] 485 | 486 | [[package]] 487 | name = "rand_hc" 488 | version = "0.3.1" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" 491 | dependencies = [ 492 | "rand_core", 493 | ] 494 | 495 | [[package]] 496 | name = "rayon" 497 | version = "1.5.1" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" 500 | dependencies = [ 501 | "autocfg", 502 | "crossbeam-deque", 503 | "either", 504 | "rayon-core", 505 | ] 506 | 507 | [[package]] 508 | name = "rayon-core" 509 | version = "1.9.1" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" 512 | dependencies = [ 513 | "crossbeam-channel", 514 | "crossbeam-deque", 515 | "crossbeam-utils", 516 | "lazy_static", 517 | "num_cpus", 518 | ] 519 | 520 | [[package]] 521 | name = "scoped-tls" 522 | version = "1.0.0" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" 525 | 526 | [[package]] 527 | name = "scoped_threadpool" 528 | version = "0.1.9" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" 531 | 532 | [[package]] 533 | name = "scopeguard" 534 | version = "1.1.0" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 537 | 538 | [[package]] 539 | name = "smallvec" 540 | version = "1.6.1" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" 543 | 544 | [[package]] 545 | name = "smithay-client-toolkit" 546 | version = "0.14.0" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "ec783683499a2cfc85b6df3d04f83b1907b5cbd98a1aed44667dbdf1eac4e64c" 549 | dependencies = [ 550 | "bitflags", 551 | "calloop", 552 | "dlib", 553 | "lazy_static", 554 | "log", 555 | "memmap2", 556 | "nix 0.20.0", 557 | "wayland-client", 558 | "wayland-cursor", 559 | "wayland-protocols", 560 | ] 561 | 562 | [[package]] 563 | name = "snui" 564 | version = "0.1.0" 565 | dependencies = [ 566 | "fontdue", 567 | "image", 568 | "smithay-client-toolkit", 569 | "wayland-client", 570 | "wayland-commons", 571 | "wayland-protocols", 572 | ] 573 | 574 | [[package]] 575 | name = "tiff" 576 | version = "0.6.1" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" 579 | dependencies = [ 580 | "jpeg-decoder", 581 | "miniz_oxide 0.4.4", 582 | "weezl", 583 | ] 584 | 585 | [[package]] 586 | name = "ttf-parser" 587 | version = "0.12.3" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6" 590 | 591 | [[package]] 592 | name = "unicode-xid" 593 | version = "0.2.2" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 596 | 597 | [[package]] 598 | name = "version_check" 599 | version = "0.9.3" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 602 | 603 | [[package]] 604 | name = "wasi" 605 | version = "0.10.2+wasi-snapshot-preview1" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 608 | 609 | [[package]] 610 | name = "wayland-client" 611 | version = "0.28.6" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "e3ab332350e502f159382201394a78e3cc12d0f04db863429260164ea40e0355" 614 | dependencies = [ 615 | "bitflags", 616 | "downcast-rs", 617 | "libc", 618 | "nix 0.20.0", 619 | "scoped-tls", 620 | "wayland-commons", 621 | "wayland-scanner", 622 | "wayland-sys", 623 | ] 624 | 625 | [[package]] 626 | name = "wayland-commons" 627 | version = "0.28.6" 628 | source = "registry+https://github.com/rust-lang/crates.io-index" 629 | checksum = "a21817947c7011bbd0a27e11b17b337bfd022e8544b071a2641232047966fbda" 630 | dependencies = [ 631 | "nix 0.20.0", 632 | "once_cell", 633 | "smallvec", 634 | "wayland-sys", 635 | ] 636 | 637 | [[package]] 638 | name = "wayland-cursor" 639 | version = "0.28.6" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "be610084edd1586d45e7bdd275fe345c7c1873598caa464c4fb835dee70fa65a" 642 | dependencies = [ 643 | "nix 0.20.0", 644 | "wayland-client", 645 | "xcursor", 646 | ] 647 | 648 | [[package]] 649 | name = "wayland-protocols" 650 | version = "0.28.6" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "286620ea4d803bacf61fa087a4242ee316693099ee5a140796aaba02b29f861f" 653 | dependencies = [ 654 | "bitflags", 655 | "wayland-client", 656 | "wayland-commons", 657 | "wayland-scanner", 658 | ] 659 | 660 | [[package]] 661 | name = "wayland-scanner" 662 | version = "0.28.6" 663 | source = "registry+https://github.com/rust-lang/crates.io-index" 664 | checksum = "ce923eb2deb61de332d1f356ec7b6bf37094dc5573952e1c8936db03b54c03f1" 665 | dependencies = [ 666 | "proc-macro2", 667 | "quote", 668 | "xml-rs", 669 | ] 670 | 671 | [[package]] 672 | name = "wayland-sys" 673 | version = "0.28.6" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "d841fca9aed7febf9bed2e9796c49bf58d4152ceda8ac949ebe00868d8f0feb8" 676 | dependencies = [ 677 | "dlib", 678 | "lazy_static", 679 | "pkg-config", 680 | ] 681 | 682 | [[package]] 683 | name = "weezl" 684 | version = "0.1.5" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e" 687 | 688 | [[package]] 689 | name = "winapi" 690 | version = "0.3.9" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 693 | dependencies = [ 694 | "winapi-i686-pc-windows-gnu", 695 | "winapi-x86_64-pc-windows-gnu", 696 | ] 697 | 698 | [[package]] 699 | name = "winapi-i686-pc-windows-gnu" 700 | version = "0.4.0" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 703 | 704 | [[package]] 705 | name = "winapi-x86_64-pc-windows-gnu" 706 | version = "0.4.0" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 709 | 710 | [[package]] 711 | name = "xcursor" 712 | version = "0.3.3" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "3a9a231574ae78801646617cefd13bfe94be907c0e4fa979cfd8b770aa3c5d08" 715 | dependencies = [ 716 | "nom", 717 | ] 718 | 719 | [[package]] 720 | name = "xml-rs" 721 | version = "0.8.3" 722 | source = "registry+https://github.com/rust-lang/crates.io-index" 723 | checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" 724 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "paper" 3 | version = "0.1.0" 4 | authors = ["Bryan Ndjeutcha "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | rand = "0.8.4" 11 | wayland-commons = "0.28.5" 12 | wayland-client = "0.28.5" 13 | smithay-client-toolkit = "0.14.0" 14 | snui = { git="https://gitlab.com/snakedye/snui.git" } 15 | wayland-protocols = { version="0.28.5", features=["unstable_protocols", "client"] } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Bryan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Paper 2 | 3 | A wallpaper daemon for Wayland compositors implementing the layer-shell protocol. 4 | 5 | ## Features 6 | 7 | - Supports png and jpg format 8 | - Tiled wallpapers 9 | - Bordered wallpapers 10 | 11 | ## Dependencies 12 | 13 | - [snui](https://gitlab.com/snakedye/snui.git) 14 | 15 | ## Building 16 | 17 | ```shell 18 | git clone https://gitlab.com/snakedye/paper.git 19 | cd paper 20 | cargo build --release 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /src/app.rs: -------------------------------------------------------------------------------- 1 | use snui::*; 2 | use std::io; 3 | use std::fs; 4 | use std::path::Path; 5 | use rand::thread_rng; 6 | use snui::wayland::*; 7 | use snui::widgets::*; 8 | use rand::seq::IteratorRandom; 9 | use std::io::Write; 10 | 11 | pub struct Paper { 12 | style: Style, 13 | pub border: Option<(u32, u32)>, 14 | pub output: Option 15 | } 16 | 17 | impl Paper { 18 | pub fn is_some(&self) -> bool { 19 | match self.style { 20 | Style::None => false, 21 | _ => true 22 | } 23 | } 24 | pub fn default() -> Self { 25 | Paper { 26 | style: Style::None, 27 | border: None, 28 | output: None 29 | } 30 | } 31 | pub fn style(&mut self, style: Style) { 32 | self.style = style 33 | } 34 | pub fn border(&mut self, gap: u32, color: u32) { 35 | self.border = Some((gap, color)); 36 | } 37 | } 38 | 39 | pub enum Style { 40 | Color(u32), 41 | Tiled(Result>), 42 | Image(Result>), 43 | Directory(String), 44 | None, 45 | } 46 | 47 | pub fn draw(buf: &mut Buffer, paper: &Paper, width: u32, height: u32) { 48 | let scale = buf.get_width()/width; 49 | match &paper.style { 50 | Style::Color(color) => { 51 | let pxcount = buf.get_width() * buf.get_height(); 52 | let mut writer = &mut buf.canvas[0..]; 53 | for _ in 0..pxcount { 54 | writer.write_all(&color.to_ne_bytes()).unwrap(); 55 | } 56 | writer.flush().unwrap(); 57 | } 58 | Style::Image(image) => if let Ok(image) = image.as_ref() { 59 | let dx = width/scale + width/(scale * 2); 60 | let dy = height/scale + height/(scale * 2); 61 | image.resize(width as u32 / scale, height as u32 / scale).draw( 62 | &mut buf.canvas, 63 | if scale > 1 { dx } else { 0 }, 64 | if scale > 1 { dy } else { 0 }, 65 | ); 66 | } 67 | Style::Tiled(image) => if let Ok(image) = image.as_ref() { 68 | let mut y = 0; 69 | let img_width = image.get_width(); 70 | let img_height = image.get_height(); 71 | while y < height { 72 | let mut x = 0; 73 | while x < width { 74 | image.draw(&mut buf.canvas, x, y); 75 | x += img_width; 76 | } 77 | y += img_height; 78 | } 79 | } 80 | Style::Directory(path) => { 81 | let dir = Path::new(&path); 82 | if dir.is_dir() { 83 | match random_image(dir, width as u32, height as u32) { 84 | Ok(image) => image.draw(&mut buf.canvas, 0, 0), 85 | Err(e) => eprintln!("{}", e) 86 | } 87 | } else { 88 | eprintln!("\"{}\" is not a directory", path); 89 | std::process::exit(1); 90 | } 91 | } 92 | _ => {} 93 | } 94 | if let Some((gap, color)) = paper.border { 95 | let border_hor = Rectangle::new(width, gap, color); 96 | let border_ver = Rectangle::new(gap, height, color); 97 | border_ver.draw(&mut buf.canvas, 0, 0); 98 | border_hor.draw(&mut buf.canvas, 0, 0); 99 | border_hor.draw(&mut buf.canvas, 0, height-gap); 100 | border_ver.draw(&mut buf.canvas, width-gap, 0); 101 | } 102 | } 103 | 104 | fn random_image(dir: &Path, width: u32, height: u32) -> io::Result { 105 | if dir.is_dir() { 106 | let mut rng = thread_rng(); 107 | if let Some(entry) = fs::read_dir(dir)?.choose(&mut rng) { 108 | let path = entry?.path(); 109 | if let Some(filename) = path.file_name() { 110 | let filename = filename.to_str().unwrap(); 111 | if filename.ends_with(".png") 112 | || filename.ends_with(".jpeg") 113 | || filename.ends_with(".jpg") { 114 | return Ok(Image::new_with_size(Path::new(path.to_str().unwrap()), width, height).unwrap()) 115 | } else if path.is_dir() { 116 | let dir = format!("{:?}", path); 117 | return random_image(Path::new(dir.trim_matches('"')), width, height) 118 | } 119 | } 120 | } else { 121 | return Err(io::Error::new(io::ErrorKind::InvalidData, "empty directory")) 122 | } 123 | } 124 | Err(io::Error::new(io::ErrorKind::InvalidData, "invalid file type")) 125 | } 126 | -------------------------------------------------------------------------------- /src/environment.rs: -------------------------------------------------------------------------------- 1 | use super::app; 2 | use snui::wayland::Buffer; 3 | use wayland_client::protocol::{ 4 | wl_compositor::WlCompositor, 5 | wl_output::{Event, WlOutput}, 6 | wl_seat::WlSeat, 7 | wl_shm::WlShm, 8 | wl_surface::WlSurface, 9 | }; 10 | use wayland_protocols::wlr::unstable::layer_shell::v1::client::{ 11 | zwlr_layer_surface_v1, 12 | }; 13 | use std::time; 14 | use smithay_client_toolkit::shm::DoubleMemPool; 15 | use wayland_client::{Display, EventQueue, GlobalManager, Main}; 16 | use wayland_protocols::wlr::unstable::layer_shell::v1::client::zwlr_layer_shell_v1::ZwlrLayerShellV1; 17 | use wayland_protocols::wlr::unstable::layer_shell::v1::client::zwlr_layer_shell_v1::Layer; 18 | 19 | pub struct Environment { 20 | pub paper: app::Paper, 21 | pub seats: Vec>, 22 | pub shm: Option>, 23 | pub compositor: Option>, 24 | pub layer_shell: Option>, 25 | } 26 | 27 | impl Environment { 28 | pub fn new(display: &Display, event_queue: &mut EventQueue, paper: app::Paper) -> Environment { 29 | let attached_display = (*display).clone().attach(event_queue.token()); 30 | let environment = Environment { 31 | paper, 32 | compositor: None, 33 | layer_shell: None, 34 | shm: None, 35 | seats: Vec::new(), 36 | }; 37 | 38 | GlobalManager::new_with_cb( 39 | &attached_display, 40 | wayland_client::global_filter!( 41 | [ 42 | ZwlrLayerShellV1, 43 | 1, 44 | |layer_shell: Main, mut environment: DispatchData| { 45 | environment.get::().unwrap().layer_shell = Some(layer_shell); 46 | } 47 | ], 48 | [ 49 | WlShm, 50 | 1, 51 | |wl_shm: Main, mut environment: DispatchData| { 52 | wl_shm.quick_assign(move |_, _, _| {}); 53 | environment.get::().unwrap().shm = Some(wl_shm); 54 | } 55 | ], 56 | [ 57 | WlSeat, 58 | 7, 59 | |wl_seat: Main, mut environment: DispatchData| { 60 | wl_seat.quick_assign(move |_, _, _| {}); 61 | environment 62 | .get::() 63 | .unwrap() 64 | .seats 65 | .push(wl_seat); 66 | } 67 | ], 68 | [ 69 | WlCompositor, 70 | 4, 71 | |wl_compositor: Main, mut environment: DispatchData| { 72 | environment.get::().unwrap().compositor = Some(wl_compositor); 73 | } 74 | ], 75 | [ 76 | WlOutput, 77 | 3, 78 | move |output: Main, mut environment: DispatchData| { 79 | if let Some(env) = environment.get::() { 80 | let surface = env.get_surface(); 81 | if env.layer_shell.is_some() && env.compositor.is_some() && env.shm.is_some() { 82 | let mut draw = true; 83 | let mut size = (0, 0); 84 | let mut scale = 1; 85 | let layer_surface = env 86 | .layer_shell 87 | .as_ref() 88 | .expect("Compositor doesn't implement the LayerShell protocol") 89 | .get_layer_surface(&surface, Some(&output), Layer::Background, String::from("wallpaper")); 90 | let attached = Attached::from(env.shm.clone().expect("No shared memory pool")); 91 | output.quick_assign(move |_, event, mut env| match event { 92 | Event::Geometry { 93 | x: _, 94 | y: _, 95 | physical_width: _, 96 | physical_height: _, 97 | subpixel: _, 98 | make, 99 | model: _, 100 | transform: _, 101 | } => if let Some(env) = env.get::() { 102 | if let Some(output) = env.paper.output.as_ref() { 103 | draw = output.eq(&make); 104 | } 105 | } 106 | Event::Mode { 107 | flags: _, 108 | width, 109 | height, 110 | refresh: _, 111 | } => { 112 | size = (width, height); 113 | } 114 | Event::Scale { factor } => { 115 | scale = factor.abs() as u32; 116 | surface.set_buffer_scale(factor); 117 | } 118 | Event::Done => { 119 | if draw { 120 | let surface = surface.clone(); 121 | layer_surface.set_size(size.0 as u32 * scale, size.1 as u32 * scale); 122 | if let Some(env) = env.get::() { 123 | if env.paper.border.is_some() { 124 | layer_surface.set_exclusive_zone(1); 125 | } else { 126 | layer_surface.set_exclusive_zone(-1); 127 | } 128 | } 129 | surface.commit(); 130 | let mut mempool = DoubleMemPool::new(attached.clone(), |_| {}).unwrap(); 131 | let mut timer: Option = None; 132 | layer_surface.quick_assign(move |layer_surface, event, mut env| match event { 133 | zwlr_layer_surface_v1::Event::Configure{serial, width, height} => { 134 | if timer.is_none() || timer.as_ref().unwrap().elapsed() > time::Duration::from_millis(600) { 135 | timer = Some(time::Instant::now()); 136 | layer_surface.ack_configure(serial); 137 | layer_surface.set_size(width, height); 138 | 139 | if let Some(mut pool) = mempool.pool() { 140 | if pool.resize((width * height) as usize * 4).is_ok() { 141 | if let Ok(mut buf) = Buffer::new( 142 | width * scale, 143 | height * scale, 144 | &mut pool, 145 | ) { 146 | if let Some(env) = env.get::() { 147 | app::draw(&mut buf, &env.paper, width, height); 148 | buf.attach(&surface, 0, 0); 149 | surface.damage( 150 | 0, 151 | 0, 152 | 1 << 30, 153 | 1 << 30 154 | ); 155 | surface.commit(); 156 | } 157 | } 158 | } 159 | } 160 | } 161 | } 162 | _ => { 163 | layer_surface.destroy(); 164 | } 165 | }); 166 | } 167 | } 168 | _ => {} 169 | }); 170 | } 171 | } 172 | } 173 | ] 174 | ), 175 | ); 176 | environment 177 | } 178 | pub fn get_surface(&self) -> Main { 179 | let wl_surface = self 180 | .compositor 181 | .as_ref() 182 | .expect("Compositor literally doesn't exist") 183 | .create_surface(); 184 | wl_surface.quick_assign(move |_, _, _| {}); 185 | wl_surface 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod app; 2 | mod environment; 3 | use std::path::Path; 4 | use snui::widgets::*; 5 | use environment::Environment; 6 | use wayland_client::{Display}; 7 | 8 | fn main() { 9 | // Command line arguments 10 | let mut args = std::env::args(); 11 | let mut paper = app::Paper::default(); 12 | args.next(); 13 | loop { 14 | match args.next() { 15 | Some(flag) => match flag.as_str() { 16 | "-c" | "--color" => { 17 | let res = u32::from_str_radix(&args.next().unwrap().trim_start_matches("#"), 16); 18 | if let Ok(color) = res { 19 | paper.style(app::Style::Color(color)); 20 | } 21 | } 22 | "-i" | "--image" => { 23 | if let Some(path) = args.next() { 24 | paper.style(app::Style::Image(Image::new(Path::new(&path)))); 25 | } 26 | } 27 | "-d" | "--dir" => { 28 | if let Some(path) = args.next() { 29 | paper.style(app::Style::Directory(path)); 30 | } 31 | } 32 | "-o" | "--output" => paper.output = args.next(), 33 | "-t" | "--tiled" => { 34 | if let Some(path) = args.next() { 35 | paper.style(app::Style::Tiled(Image::new(Path::new(&path)))); 36 | } 37 | } 38 | "-b" | "--border" => { 39 | if let Some(gap) = args.next() { 40 | if let Ok(gap) = gap.parse::() { 41 | let res = u32::from_str_radix(&args.next().unwrap().trim_start_matches("#"), 16); 42 | if let Ok(color) = res { 43 | paper.border(gap, color); 44 | } 45 | } 46 | } 47 | } 48 | "-h" | "--help" => { 49 | print!("Usage: paper [option]\n\n"); 50 | print!(" -c | --color #AARRGGBB\n"); 51 | print!(" -t | --tile /path/to/image\n"); 52 | print!(" -i | --image /path/to/image\n"); 53 | print!(" -d | --dir /path/to/directory\n"); 54 | print!(" -o | --output the name of your output\n"); 55 | println!(" -b | --border border_size #AARRGGBB\n"); 56 | } 57 | _ => break 58 | } 59 | None => break 60 | } 61 | } 62 | 63 | if paper.is_some() { 64 | let display = Display::connect_to_env().unwrap(); 65 | let mut event_queue = display.create_event_queue(); 66 | let mut environment = Environment::new(&display, &mut event_queue, paper); 67 | 68 | loop { 69 | event_queue 70 | .dispatch(&mut environment, |event, object, _| { 71 | panic!( 72 | "[callop] Encountered an orphan event: {}@{}: {}", 73 | event.interface, 74 | object.as_ref().id(), 75 | event.name 76 | ); 77 | }) 78 | .unwrap(); 79 | } 80 | } 81 | } 82 | --------------------------------------------------------------------------------