diff options
-rw-r--r-- | Cargo.lock | 628 | ||||
-rw-r--r-- | Cargo.toml | 12 | ||||
-rw-r--r-- | src/bin/fragment.frag | 7 | ||||
-rw-r--r-- | src/bin/phosphor_test.rs | 97 | ||||
-rw-r--r-- | src/bin/vertex.vert | 9 | ||||
-rw-r--r-- | src/keyboard_input.rs | 19 | ||||
-rw-r--r-- | src/lib.rs | 60 | ||||
-rw-r--r-- | src/press_state.rs | 26 | ||||
-rw-r--r-- | src/program_controller.rs | 13 | ||||
-rw-r--r-- | src/render.rs | 67 | ||||
-rw-r--r-- | src/render_hint.rs | 33 | ||||
-rw-r--r-- | src/render_request.rs | 40 | ||||
-rw-r--r-- | src/window.rs | 177 | ||||
-rw-r--r-- | src/window/x11.rs | 66 | ||||
-rw-r--r-- | src/window_controller.rs | 56 | ||||
-rw-r--r-- | src/window_manager.rs | 198 |
16 files changed, 926 insertions, 582 deletions
@@ -27,12 +27,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] +name = "as-raw-xcb-connection" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5f312b0a56c5cdf967c0aeb67f6289603354951683bc97ddc595ab974ba9aa" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] name = "block-sys" version = "0.1.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -66,6 +84,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] +name = "bytemuck" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -88,6 +126,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics 0.23.1", + "foreign-types 0.5.0", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags", + "block", + "core-foundation", + "core-graphics-types", + "libc", + "objc", +] + +[[package]] name = "colour" version = "1.0.0" dependencies = [ @@ -119,7 +187,20 @@ dependencies = [ "bitflags", "core-foundation", "core-graphics-types", - "foreign-types", + "foreign-types 0.3.2", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212" +dependencies = [ + "bitflags", + "core-foundation", + "core-graphics-types", + "foreign-types 0.5.0", "libc", ] @@ -131,23 +212,113 @@ checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" dependencies = [ "bitflags", "core-foundation", - "foreign-types", + "foreign-types 0.3.2", "libc", ] [[package]] +name = "ctor" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" +dependencies = [ + "quote", + "syn 2.0.28", +] + +[[package]] name = "dispatch" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading 0.8.1", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "drm" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf9159ef4bcecd0c5e4cbeb573b8d0037493403d542780dba5d840bbf9df56f" +dependencies = [ + "bitflags", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "nix", +] + +[[package]] +name = "drm-ffi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1352481b7b90e27a8a1bf8ef6b33cf18b98dba7c410e75c24bb3eef2f0d8d525" +dependencies = [ + "drm-sys", + "nix", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1369f1679d6b706d234c4c1e0613c415c2c74b598a09ad28080ba2474b72e42d" +dependencies = [ + "libc", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared", + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", ] [[package]] @@ -157,10 +328,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] name = "geometry" version = "0.1.0" [[package]] +name = "gethostname" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] name = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -173,6 +366,17 @@ dependencies = [ ] [[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + +[[package]] name = "jni-sys" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -189,9 +393,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -204,9 +408,29 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.135" +version = "0.2.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] [[package]] name = "log" @@ -218,6 +442,39 @@ dependencies = [ ] [[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "memmap2" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] name = "mio" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -259,8 +516,17 @@ dependencies = [ ] [[package]] -name = "nosferatu" -version = "0.1.0" +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags", + "cfg-if", + "libc", + "memoffset", + "pin-utils", +] [[package]] name = "num_enum" @@ -289,7 +555,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.102", + "syn 1.0.107", ] [[package]] @@ -301,7 +567,16 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.28", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", ] [[package]] @@ -332,9 +607,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.15.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "orbclient" @@ -357,13 +632,23 @@ version = "0.1.0" dependencies = [ "buffer", "geometry", - "nosferatu", - "raw-window-handle", + "softbuffer", "winit", - "x11-dl", ] [[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] name = "pkg-config" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -394,6 +679,15 @@ name = "proportion" version = "1.0.0" [[package]] +name = "quick-xml" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" +dependencies = [ + "memchr", +] + +[[package]] name = "quote" version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -418,16 +712,60 @@ dependencies = [ ] [[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] name = "serde" version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" [[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + +[[package]] +name = "softbuffer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd56fe5e6c6f1881aad2bd37acaef4ac4a3689c970dfcbd87a36a6e60210ec8" +dependencies = [ + "as-raw-xcb-connection", + "bytemuck", + "cfg_aliases", + "cocoa", + "core-graphics 0.23.1", + "drm", + "drm-sys", + "fastrand", + "foreign-types 0.5.0", + "js-sys", + "log", + "memmap2", + "nix", + "objc", + "raw-window-handle", + "redox_syscall", + "tiny-xlib", + "wasm-bindgen", + "wayland-backend", + "wayland-client", + "wayland-sys", + "web-sys", + "windows-sys 0.48.0", + "x11rb", +] + +[[package]] name = "syn" -version = "1.0.102" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -436,9 +774,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.32" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -447,22 +785,34 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 1.0.102", + "syn 2.0.28", +] + +[[package]] +name = "tiny-xlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4098d49269baa034a8d1eae9bd63e9fa532148d772121dace3bcd6a6c98eb6d" +dependencies = [ + "as-raw-xcb-connection", + "ctor", + "libloading 0.8.1", + "tracing", ] [[package]] @@ -475,6 +825,23 @@ dependencies = [ ] [[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" + +[[package]] name = "unicode-ident" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -488,9 +855,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -498,24 +865,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.102", + "syn 2.0.28", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -523,22 +890,49 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.102", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "wayland-backend" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b48e27457e8da3b2260ac60d0a94512f5cba36448679f3747c0865b7893ed8" +dependencies = [ + "cc", + "downcast-rs", + "io-lifetimes", + "nix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.30.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489c9654770f674fc7e266b3c579f4053d7551df0ceb392f153adb1f9ed06ac8" +dependencies = [ + "bitflags", + "nix", + "wayland-backend", + "wayland-scanner 0.30.1", +] [[package]] name = "wayland-scanner" @@ -552,16 +946,70 @@ dependencies = [ ] [[package]] +name = "wayland-scanner" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b873b257fbc32ec909c0eb80dea312076a67014e65e245f5eb69a6b8ab330e" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b2a02ac608e07132978689a6f9bf4214949c85998c247abadd4f4129b1aa06" +dependencies = [ + "dlib", + "lazy_static", + "log", + "pkg-config", +] + +[[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-wsapoll" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] name = "windows-sys" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -580,7 +1028,16 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -589,22 +1046,43 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows_aarch64_gnullvm", + "windows_aarch64_gnullvm 0.42.2", "windows_aarch64_msvc 0.42.2", "windows_i686_gnu 0.42.2", "windows_i686_msvc 0.42.2", "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm", + "windows_x86_64_gnullvm 0.42.2", "windows_x86_64_msvc 0.42.2", ] [[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -617,6 +1095,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -629,6 +1113,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -641,6 +1131,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -653,12 +1149,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -671,6 +1179,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] name = "winit" version = "0.28.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -680,7 +1194,7 @@ dependencies = [ "bitflags", "cfg_aliases", "core-foundation", - "core-graphics", + "core-graphics 0.22.3", "dispatch", "instant", "libc", @@ -694,7 +1208,7 @@ dependencies = [ "raw-window-handle", "redox_syscall", "wasm-bindgen", - "wayland-scanner", + "wayland-scanner 0.29.5", "web-sys", "windows-sys 0.45.0", "x11-dl", @@ -712,6 +1226,32 @@ dependencies = [ ] [[package]] +name = "x11rb" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading 0.7.4", + "nix", + "once_cell", + "winapi", + "winapi-wsapoll", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" +dependencies = [ + "nix", +] + +[[package]] name = "xml-rs" version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6,12 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -winit = { version = "0.27.4", default-features = false, features = ["x11"] } -x11-dl = "2.19.1" -raw-window-handle = "0.4.2" -# raw-gl-context = "0.1.2" -# gl = "0.14" - -geometry = { path = "/home/ben/Libraries/geometry" } -nosferatu = { path = "/home/ben/Libraries/nosferatu" } buffer = { path = "/home/ben/Libraries/buffer" } +geometry = { path = "/home/ben/Libraries/geometry" } + +softbuffer = "0.3.1" +winit = { version = "0.28.1", default-features = false, features = ["x11"] } diff --git a/src/bin/fragment.frag b/src/bin/fragment.frag deleted file mode 100644 index 99826f6..0000000 --- a/src/bin/fragment.frag +++ /dev/null @@ -1,7 +0,0 @@ -#version 330 -out vec4 FragColor; -in vec3 vertexColor; - -void main() { - FragColor = vec4(vertexColor, 1.0); -} diff --git a/src/bin/phosphor_test.rs b/src/bin/phosphor_test.rs index 40a8558..c3b307d 100644 --- a/src/bin/phosphor_test.rs +++ b/src/bin/phosphor_test.rs @@ -1,89 +1,36 @@ -#![allow(dead_code)] - -// use asbestos::{Shader, ShaderProgram}; use buffer::*; use phosphor::*; -// use raw_gl_context::GlContext; fn main() { - let my_program = MyProgram {}; - let mut wm = WindowManager::with_program(my_program); - wm.create_window(MainWindow::new()); + let mut wm = WindowManager::new(std::time::Duration::from_micros(16666)); + wm.add_window(Box::new(Window {})); wm.run() } -struct MyProgram {} -impl ProgramController for MyProgram {} - -struct MainWindow { - // program: ShaderProgram, -} -impl MainWindow { - pub fn new() -> Box<Self> { - // let vertex_shader = Shader::vertex(include_str!("vertex.vert")); - // let fragment_shader = Shader::fragment(include_str!("fragment.frag")); - // let program = ShaderProgram::from_shaders(&[vertex_shader, fragment_shader]); - // Box::new(Self { program }) - Box::new(Self {}) +struct Window {} +impl WindowController for Window { + fn minimum_size(&self) -> Option<phosphor::Dimensions> { + Some(phosphor::Dimensions::new(200, 200)) } -} -impl WindowController for MainWindow { - fn render(&mut self, buffer: &mut Buffer, _: RenderHint) { - println!("Rendering..."); - buffer.fill(Colour::TEAL); + fn maximum_size(&self) -> Option<phosphor::Dimensions> { + Some(phosphor::Dimensions::new(400, 400)) } - // fn render_gl(&mut self, _context: &mut GlContext) { - // println!("Rendering GL..."); - // unsafe { - // gl::ClearColor(1.0, 0.0, 1.0, 1.0); - // gl::Clear(gl::COLOR_BUFFER_BIT); - // } - // } -} - -// type Pos = [f32; 2]; -// type Color = [f32; 3]; -// #[repr(C, packed)] -// struct Vertex(Pos, Color); - -// const VERTICES: [Vertex; 3] = [ -// Vertex([-0.5, -0.5], [1.0, 0.0, 0.0]), -// Vertex([0.5, -0.5], [0.0, 1.0, 0.0]), -// Vertex([0.0, 0.5], [0.0, 0.0, 1.0]) -// ]; + fn render_request(&self) -> RenderRequest { + RenderRequest::None + } -// pub struct Buffer { -// pub id: GLuint, -// target: GLuint, -// } -// impl Buffer { -// pub unsafe fn new(target: GLuint) -> Self { -// let mut id: GLuint = 0; -// gl::GenBuffers(1, &mut id); -// Self { id, target } -// } + fn is_resizable(&self) -> bool { + false + } -// pub unsafe fn bind(&self) { -// gl::BindBuffer(self.target, self.id); -// } + fn on_resize(&mut self, size: phosphor::Dimensions) { + println!("RESIZE: {size:?}"); + } -// pub unsafe fn set_data<D>(&self, data: &[D], usage: GLuint) { -// self.bind(); -// let (_, data_bytes, _) = data.align_to::<u8>(); -// gl::BufferData( -// self.target, -// data_bytes.len() as GLsizeiptr, -// data_bytes.as_ptr() as *const _, -// usage, -// ); -// } -// } + fn on_render(&mut self, buffer: &mut Buffer, _: RenderHint) { + println!("RENDER"); + buffer.fill(Colour::TEAL); + } +} -// impl Drop for Buffer { -// fn drop(&mut self) { -// unsafe { -// gl::DeleteBuffers(1, [self.id].as_ptr()); -// } -// } -// } diff --git a/src/bin/vertex.vert b/src/bin/vertex.vert deleted file mode 100644 index 0fd4f8a..0000000 --- a/src/bin/vertex.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 330 -in vec2 point; -in vec3 color; -out vec3 vertexColor; - -void main() { - gl_Point = vec4(point, 0.0, 1.0); - vertexColor = color; -} diff --git a/src/keyboard_input.rs b/src/keyboard_input.rs deleted file mode 100644 index 139db7e..0000000 --- a/src/keyboard_input.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::*; -use winit::event::KeyboardInput as WinitKeyboardInput; - -#[derive(Copy, Clone)] -pub struct KeyboardInput { - pub state: PressState, - pub keycode: Option<KeyCode>, - pub scancode: u32, -} - -impl From<WinitKeyboardInput> for KeyboardInput { - fn from(input: WinitKeyboardInput) -> Self { - Self { - state: input.state.into(), - keycode: input.virtual_keycode, - scancode: input.scancode, - } - } -} @@ -1,25 +1,16 @@ -mod keyboard_input; -mod press_state; -mod program_controller; -mod render_hint; -mod render_request; +mod render; mod window; mod window_controller; mod window_manager; -use window::Window; - -pub use keyboard_input::KeyboardInput; -pub use press_state::PressState; -pub use program_controller::{DefaultProgramController, ProgramController}; -pub use render_hint::RenderHint; -pub use render_request::RenderRequest; -pub use window_controller::WindowController; -pub use window_manager::WindowManager; +pub use render::*; +pub use window::*; +pub use window_controller::*; +pub use window_manager::*; pub use buffer::{Buffer, Colour}; pub use winit::{ - event::ModifiersState, + event::{ModifiersState, ElementState}, event::VirtualKeyCode as KeyCode, window::CursorIcon, }; @@ -27,3 +18,42 @@ pub use winit::{ pub type Point = geometry::Point<i32>; pub type Dimensions = geometry::Dimensions<u32>; pub type Rect = geometry::Rect<i32, u32>; + +// ----------------------------------------------------------------------------- + +#[derive(Copy, Clone)] +pub struct KeyboardInput { + pub action: Action, + pub key: KeyCode, +} + +impl TryFrom<winit::event::KeyboardInput> for KeyboardInput { + type Error = (); + + fn try_from(input: winit::event::KeyboardInput) -> Result<Self, ()> { + if let Some(key) = input.virtual_keycode { + Ok( Self { action: input.state.into(), key } ) + } else { + Err(()) + } + } +} + +// ----------------------------------------------------------------------------- + +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum Action { Pressed, Released } + +impl Action { + pub fn is_pressed(&self) -> bool { *self == Self::Pressed } + pub fn is_released(&self) -> bool { *self == Self::Released } +} + +impl From<ElementState> for Action { + fn from(value: ElementState) -> Self { + match value { + ElementState::Pressed => Action::Pressed, + ElementState::Released => Action::Released, + } + } +} diff --git a/src/press_state.rs b/src/press_state.rs deleted file mode 100644 index 5136d66..0000000 --- a/src/press_state.rs +++ /dev/null @@ -1,26 +0,0 @@ -use winit::event::ElementState; - -/// Denotes whether an event was a press event or a release event. -#[derive(Clone, Copy, PartialEq, Debug)] -pub enum PressState { - Pressed, - Released, -} - -impl PressState { - pub fn is_pressed(&self) -> bool { - *self == Self::Pressed - } - pub fn is_released(&self) -> bool { - *self == Self::Released - } -} - -impl From<ElementState> for PressState { - fn from(value: ElementState) -> Self { - match value { - ElementState::Pressed => PressState::Pressed, - ElementState::Released => PressState::Released, - } - } -} diff --git a/src/program_controller.rs b/src/program_controller.rs deleted file mode 100644 index 638e5ce..0000000 --- a/src/program_controller.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::*; - -pub trait ProgramController { - fn initialise(&mut self) {} - fn on_render(&mut self) {} - fn on_mouse_moved(&mut self, _position: Point) {} - - fn on_process(&mut self, _create_window: &mut dyn FnMut(Box<dyn WindowController>)) {} -} - -/// An empty program controller, for when a program has only one window. -pub struct DefaultProgramController {} -impl ProgramController for DefaultProgramController {} diff --git a/src/render.rs b/src/render.rs new file mode 100644 index 0000000..e7ec02d --- /dev/null +++ b/src/render.rs @@ -0,0 +1,67 @@ +/// Tells a window controller whether the previous render state is intact and +/// can be updated, or was destroyed and needs to be fully redrawn. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum RenderHint { + /// The buffer content is unchanged, only updates are required. + Update, + /// The buffer content has been destroyed, a full redraw is required. + Redraw, +} + +impl RenderHint { + pub fn is_update(&self) -> bool { *self == RenderHint::Update } + pub fn is_redraw(&self) -> bool { *self == RenderHint::Redraw } +} + +impl std::ops::BitAnd for RenderHint { + type Output = RenderHint; + fn bitand(self, other: RenderHint) -> Self::Output { + if self == RenderHint::Redraw || other == RenderHint::Redraw { + RenderHint::Redraw + } else { + RenderHint::Update + } + } +} + +impl std::ops::BitAndAssign for RenderHint { + fn bitand_assign(&mut self, other: RenderHint) { + *self = *self & other; + } +} + +/// A request to the window manager for a render pass to be run. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum RenderRequest { + None, + Render(RenderHint), +} + +impl RenderRequest { + pub const NONE: RenderRequest = RenderRequest::None; + pub const UPDATE: RenderRequest = RenderRequest::Render(RenderHint::Update); + pub const REDRAW: RenderRequest = RenderRequest::Render(RenderHint::Redraw); + + pub fn is_none(&self) -> bool { *self == RenderRequest::None } + pub fn is_some(&self) -> bool { *self != RenderRequest::None } + pub fn is_update(&self) -> bool { *self == RenderRequest::UPDATE } + pub fn is_redraw(&self) -> bool { *self == RenderRequest::REDRAW } +} + +impl std::ops::BitAnd for RenderRequest { + type Output = RenderRequest; + fn bitand(self, other: RenderRequest) -> Self::Output { + use RenderRequest::*; + match (self, other) { + (None, req) => req, + (req, None) => req, + (Render(a), Render(b)) => Render(a & b), + } + } +} + +impl std::ops::BitAndAssign for RenderRequest { + fn bitand_assign(&mut self, other: RenderRequest) { + *self = *self & other; + } +} diff --git a/src/render_hint.rs b/src/render_hint.rs deleted file mode 100644 index e4d37c3..0000000 --- a/src/render_hint.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::ops::*; - -/// A hint to tell a window controller whether the previous render state is -/// intact and can be updated, or was destroyed and needs to be fully redrawn. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum RenderHint { - /// The buffer contents are intact, only updates need to be drawn. - Update, - /// The buffer contents were destroyed, a full redraw is required. - Redraw, -} - -impl RenderHint { - pub fn is_update(&self) -> bool { *self == RenderHint::Update } - pub fn is_redraw(&self) -> bool { *self == RenderHint::Redraw } -} - -impl BitAnd for RenderHint { - type Output = RenderHint; - fn bitand(self, other: RenderHint) -> Self::Output { - if self == RenderHint::Redraw || other == RenderHint::Redraw { - RenderHint::Redraw - } else { - RenderHint::Update - } - } -} - -impl BitAndAssign for RenderHint { - fn bitand_assign(&mut self, other: RenderHint) { - *self = *self & other; - } -} diff --git a/src/render_request.rs b/src/render_request.rs deleted file mode 100644 index f336dfc..0000000 --- a/src/render_request.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::*; -use std::ops::*; - -/// A request to the window manager for a render pass to be run. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum RenderRequest { - /// A render is not required. - None, - /// A render is required. - Render(RenderHint), -} - -impl RenderRequest { - pub const NONE: RenderRequest = RenderRequest::None; - pub const UPDATE: RenderRequest = RenderRequest::Render(RenderHint::Update); - pub const REDRAW: RenderRequest = RenderRequest::Render(RenderHint::Redraw); - - pub fn is_none(&self) -> bool { *self == RenderRequest::NONE } - pub fn is_some(&self) -> bool { *self != RenderRequest::None } - pub fn is_update(&self) -> bool { *self == RenderRequest::UPDATE } - pub fn is_redraw(&self) -> bool { *self == RenderRequest::REDRAW } -} - -impl BitAnd for RenderRequest { - type Output = RenderRequest; - fn bitand(self, other: RenderRequest) -> Self::Output { - use RenderRequest::*; - match (self, other) { - (None, req) => req, - (req, None) => req, - (Render(a), Render(b)) => Render(a & b), - } - } -} - -impl BitAndAssign for RenderRequest { - fn bitand_assign(&mut self, other: RenderRequest) { - *self = *self & other; - } -} diff --git a/src/window.rs b/src/window.rs index 45e37c9..ffe35e8 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,136 +1,133 @@ -mod x11; use crate::*; -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; + +use std::num::NonZeroU32; use winit::dpi::{Size, PhysicalSize}; use winit::event_loop::EventLoopWindowTarget; -use winit::window::{WindowId, Window as WinitWindow, WindowBuilder as WinitWindowBuilder}; -// use raw_gl_context::{GlConfig, GlContext}; +use winit::window::WindowId; pub struct Window { pub controller: Box<dyn WindowController>, - cursor_position: Option<Point>, - winit_window: WinitWindow, + window: winit::window::Window, buffer: Buffer, dimensions: Dimensions, - /// The most recent render request for this window. - render_hint: RenderHint, - graphics_context: Box<dyn GraphicsContext>, - // gl_context: GlContext, + #[allow(dead_code)] context: softbuffer::Context, + surface: softbuffer::Surface, + current_render_hint: RenderHint, + previous_cursor_position: Option<Point>, } impl Window { - pub unsafe fn new(event_loop: &EventLoopWindowTarget<()>, controller: Box<dyn WindowController>) -> Self { - let mut builder = WinitWindowBuilder::new(); - builder = builder.with_resizable(controller.resizable()); - builder = builder.with_inner_size({ - let dim = controller.initial_dimensions(); - Size::Physical(PhysicalSize::new(dim.width, dim.height)) - }); - if let Some(dim) = controller.minimum_dimensions() { - let size = Size::Physical(PhysicalSize { width: dim.width, height: dim.height }); - builder = builder.with_min_inner_size(size); - } - if let Some(dim) = controller.maximum_dimensions() { - let size = Size::Physical(PhysicalSize { width: dim.width, height: dim.height }); - builder = builder.with_max_inner_size(size); - } - let winit_window = builder.build(event_loop).unwrap(); + pub fn new(event_loop: &EventLoopWindowTarget<()>, controller: Box<dyn WindowController>) -> Self { + let window = winit::window::WindowBuilder::new() + .with_title(controller.title()) + .with_resizable(controller.is_resizable()) + .with_inner_size(dim_to_size(controller.initial_size())) + .build(event_loop) + .unwrap(); + + let context = unsafe { softbuffer::Context::new(&window) }.unwrap(); + let surface = unsafe { softbuffer::Surface::new(&context, &window) }.unwrap(); - let graphics_context: Box<dyn GraphicsContext> = match winit_window.raw_window_handle() { - RawWindowHandle::Xlib(xlib_handle) => Box::new(x11::X11GraphicsContext::new(xlib_handle)), - _ => panic!("Unknown window handle type"), - }; - // let gl_context = GlContext::create(&winit_window, GlConfig::default()).unwrap(); - // gl_context.make_current(); - // gl::load_with(|symbol| { - // println!("Loaded '{}'", symbol); - // gl_context.get_proc_address(symbol) as *const _ - // }); Self { - winit_window, controller, - graphics_context, - render_hint: RenderHint::Redraw, - // gl_context, + window, buffer: Buffer::new(Dimensions::ZERO), dimensions: Dimensions::ZERO, - cursor_position: None, + context, + surface, + previous_cursor_position: None, + current_render_hint: RenderHint::Redraw, } } pub fn id(&self) -> WindowId { - self.winit_window.id() + self.window.id() } - pub fn set_minimum_dimensions(&mut self, dimensions: Option<Dimensions>) { - self.winit_window.set_min_inner_size(dimensions.map(|dim| { - Size::Physical(PhysicalSize { width:dim.width, height:dim.height }) - })) + pub fn update_title(&mut self) { + self.window.set_title(&self.controller.title()); } - pub fn set_maximum_dimensions(&mut self, dimensions: Option<Dimensions>) { - self.winit_window.set_max_inner_size(dimensions.map(|dim| { - Size::Physical(PhysicalSize { width:dim.width, height:dim.height }) - })) + + pub fn update_cursor_icon(&mut self) { + let icon = self.controller.cursor_icon().unwrap_or(CursorIcon::Default); + self.window.set_cursor_icon(icon); } - pub fn set_title(&mut self, title: &str) { - self.winit_window.set_title(title); + + pub fn update_minimum_size(&mut self) { + let size = self.controller.minimum_size().map(|d| dim_to_size(d)); + self.window.set_min_inner_size(size); } - /// Call to update the frame buffer to the new size of the window. - pub fn resize_buffer(&mut self, dimensions: Dimensions) { - if self.dimensions == dimensions { return } - self.dimensions = dimensions; - self.buffer.resize(dimensions); - self.controller.on_resize(dimensions); - self.render_hint = RenderHint::Redraw; + pub fn update_maximum_size(&mut self) { + let size = self.controller.maximum_size().map(|d| dim_to_size(d)); + self.window.set_max_inner_size(size); } - pub fn set_cursor_icon(&mut self, icon: Option<CursorIcon>) { - match icon { - Some(icon) => self.winit_window.set_cursor_icon(icon), - None => self.winit_window.set_cursor_icon(CursorIcon::Default), - }; + pub fn update_cursor_visible(&mut self) { + self.window.set_cursor_visible(self.controller.is_cursor_visible()); } - /// Call this after a mouse click so that the cursor-hovering callbacks are - /// rerun. This is useful where a click changes the UI layout and a new - /// element that has an on-hover effect appears beneath the cursor. - pub fn bump_mouse(&mut self) { - if let Some(position) = self.cursor_position { - self.controller.on_mouse_move(position) + pub fn update_resizable(&mut self) { + let is_resizable = self.controller.is_resizable(); + self.window.set_resizable(is_resizable); + // Hack to force window to be impossible to resize on DWM, where the + // 'is_resizable' window attribute isn't respected. + if !is_resizable { + self.window.set_min_inner_size(Some(self.window.inner_size())); + self.window.set_max_inner_size(Some(self.window.inner_size())); } } - pub fn move_mouse(&mut self, position: Point) { - if self.cursor_position != Some(position) { - self.cursor_position = Some(position); - self.controller.on_mouse_move(position); + /// Resize the frame buffer to be the new size of the window. + pub fn resize(&mut self, dimensions: Dimensions) { + if self.dimensions == dimensions { return } + self.dimensions = dimensions; + self.buffer.resize(dimensions); + if let Some((width, height)) = dim_to_nonzero_size(dimensions) { + self.surface.resize(width, height).unwrap(); + }; + self.controller.on_resize(dimensions); + self.current_render_hint = RenderHint::Redraw; + } + + pub fn move_cursor(&mut self, position: Point) { + // The cursor position is rounded to i32 from f64, so we need to ignore + // duplicate consecutive cursor positions. + if self.previous_cursor_position != Some(position) { + self.previous_cursor_position = Some(position); + self.controller.on_cursor_move(position); } } - pub fn check_render_request(&mut self) { + pub fn handle_render_request(&mut self) { if let RenderRequest::Render(hint) = self.controller.render_request() { - self.render_hint &= hint; - self.winit_window.request_redraw(); + self.current_render_hint &= hint; + self.window.request_redraw(); } } pub fn render(&mut self) { - self.controller.render(&mut self.buffer, self.render_hint); - unsafe { self.graphics_context.blit(&self.buffer); } - // Reset the render_hint back to the lowest variant. - self.render_hint = RenderHint::Update; + let size = self.window.inner_size(); + let dim = Dimensions::new(size.width, size.height); + self.resize(dim); + self.controller.on_render(&mut self.buffer, self.current_render_hint); + let buffer = self.buffer.as_u32_slice(); + let mut surface = self.surface.buffer_mut().unwrap(); + let buffer_len = buffer.len(); + let surface_len = surface.len(); + surface[..buffer_len].copy_from_slice(&buffer[..surface_len]); + surface.present().unwrap(); + // Reset current_render_hint back to the lowest variant for the next frame. + self.current_render_hint = RenderHint::Update; } +} - // pub fn render_gl(&mut self) { - // self.gl_context.make_current(); - // self.controller.render_gl(&mut self.gl_context); - // self.gl_context.swap_buffers(); - // self.gl_context.make_not_current(); - // } +fn dim_to_size(dimensions: Dimensions) -> Size { + Size::Physical( PhysicalSize { width:dimensions.width, height:dimensions.height }) } -trait GraphicsContext { - /// Fill the graphics context with the contents of the provided buffer. - unsafe fn blit(&mut self, buffer: &Buffer); +fn dim_to_nonzero_size(dimensions: Dimensions) -> Option<(NonZeroU32, NonZeroU32)> { + let width = NonZeroU32::new(dimensions.width)?; + let height = NonZeroU32::new(dimensions.height)?; + return Some((width, height)); } diff --git a/src/window/x11.rs b/src/window/x11.rs deleted file mode 100644 index d4bcbe4..0000000 --- a/src/window/x11.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::window::GraphicsContext; -use buffer::Buffer; -use geometry::HasDimensions; -use raw_window_handle::XlibHandle; -use std::os::raw::{c_char, c_uint}; -use x11_dl::xlib::{Display, Visual, Xlib, ZPixmap, GC}; - -pub struct X11GraphicsContext { - handle: XlibHandle, - lib: Xlib, - gc: GC, - visual: *mut Visual, - depth: i32, -} - -impl X11GraphicsContext { - pub unsafe fn new(handle: XlibHandle) -> Self { - let lib = match Xlib::open() { - Ok(lib) => lib, - Err(e) => panic!("{:?}", e), - }; - let screen = (lib.XDefaultScreen)(handle.display as *mut Display); - let gc = (lib.XDefaultGC)(handle.display as *mut Display, screen); - let visual = (lib.XDefaultVisual)(handle.display as *mut Display, screen); - let depth = (lib.XDefaultDepth)(handle.display as *mut Display, screen); - - Self { handle, lib, gc, visual, depth } - } -} - -impl GraphicsContext for X11GraphicsContext { - unsafe fn blit(&mut self, buffer: &Buffer) { - let array = buffer.as_u32_slice(); - let dimensions = buffer.dimensions(); - //create image - let image = (self.lib.XCreateImage)( - self.handle.display as *mut Display, - self.visual, - self.depth as u32, - ZPixmap, - 0, - (array.as_ptr()) as *mut c_char, - dimensions.width as u32, - dimensions.height as u32, - 32, - (dimensions.width * 4) as i32, - ); - - //push image to window - (self.lib.XPutImage)( - self.handle.display as *mut Display, - self.handle.window, - self.gc, - image, - 0, - 0, - 0, - 0, - dimensions.width as c_uint, - dimensions.height as c_uint, - ); - - (*image).data = std::ptr::null_mut(); - (self.lib.XDestroyImage)(image); - } -} diff --git a/src/window_controller.rs b/src/window_controller.rs index d088b99..34f9fd4 100644 --- a/src/window_controller.rs +++ b/src/window_controller.rs @@ -1,42 +1,44 @@ use crate::*; -// use raw_gl_context::GlContext; -/// Controls a single window. pub trait WindowController { fn title(&self) -> String { String::from("Phosphor") } - fn initial_dimensions(&self) -> Dimensions { Dimensions::new(800,600) } - fn minimum_dimensions(&self) -> Option<Dimensions> { None } - fn maximum_dimensions(&self) -> Option<Dimensions> { None } - fn resizable(&self) -> bool { true } - - fn cursor_icon(&mut self) -> Option<CursorIcon> { None } - fn cursor_visible(&mut self) -> bool { true } - - fn on_resize(&mut self, _dimensions: Dimensions) {} + fn cursor_icon(&self) -> Option<CursorIcon> { None } + fn initial_size(&self) -> Dimensions { Dimensions::new(800,600) } + fn minimum_size(&self) -> Option<Dimensions> { None } + fn maximum_size(&self) -> Option<Dimensions> { None } + fn pixel_scale(&self) -> u32 { 1 } + fn render_request(&self) -> RenderRequest { RenderRequest::None } + + fn is_visible(&self) -> bool { true } + fn is_cursor_visible(&self) -> bool { true } + fn is_resizable(&self) -> bool { true } + + fn on_init(&mut self) {} + fn on_resize(&mut self, _size: Dimensions) {} fn on_move(&mut self, _position: Point) {} - fn on_focus_change(&mut self, _focused: bool) {} + fn on_focus_change(&mut self, _is_focused: bool) {} fn on_process(&mut self) {} + fn on_render(&mut self, _buffer: &mut Buffer, _hint: RenderHint) {} + fn on_close_request(&mut self) {} + fn on_close(&mut self) {} - fn on_mouse_enter(&mut self) {} - fn on_mouse_exit(&mut self) {} - fn on_mouse_move(&mut self, _position: Point) {} + fn on_cursor_enter(&mut self) {} + fn on_cursor_exit(&mut self) {} + fn on_cursor_move(&mut self, _position: Point) {} - fn on_left_mouse_button(&mut self, _pressed: PressState) {} - fn on_middle_mouse_button(&mut self, _pressed: PressState) {} - fn on_right_mouse_button(&mut self, _pressed: PressState) {} - - fn on_keyboard_input(&mut self, _input: KeyboardInput) {} - fn on_keyboard_modifier_change(&mut self, _modifiers: ModifiersState) {} - fn on_character_received(&mut self, _character: char) {} - fn on_file_hovered(&mut self, _path: std::path::PathBuf) {} - fn on_file_dropped(&mut self, _path: std::path::PathBuf) {} + fn on_left_mouse_button(&mut self, _action: Action) {} + fn on_middle_mouse_button(&mut self, _action: Action) {} + fn on_right_mouse_button(&mut self, _action: Action) {} fn on_line_scroll_horizontal(&mut self, _delta: f64) {} fn on_line_scroll_vertical(&mut self, _delta: f64) {} fn on_pixel_scroll_horizontal(&mut self, _delta: f64) {} fn on_pixel_scroll_vertical(&mut self, _delta: f64) {} - fn render_request(&mut self) -> RenderRequest { RenderRequest::None } - fn render(&mut self, _buffer: &mut Buffer, _hint: RenderHint) {} - // fn render_gl(&mut self, _context: &mut GlContext) {} + fn on_keyboard_input(&mut self, _input: KeyboardInput) {} + fn on_keyboard_modifier_change(&mut self, _modifiers: ModifiersState) {} + fn on_character_input(&mut self, _character: char) {} + fn on_file_hover(&mut self, _path: std::path::PathBuf) {} + fn on_file_hover_cancel(&mut self) {} + fn on_file_drop(&mut self, _path: std::path::PathBuf) {} } diff --git a/src/window_manager.rs b/src/window_manager.rs index 144f1c3..065d517 100644 --- a/src/window_manager.rs +++ b/src/window_manager.rs @@ -1,156 +1,134 @@ use crate::*; -use nosferatu::*; - use std::collections::HashMap; -use winit::event::{Event, MouseButton, StartCause, WindowEvent, MouseScrollDelta}; -use winit::event_loop::EventLoop; -use winit::window::WindowId; - -/// Controls the entire program. -pub struct WindowManager<P: ProgramController> { - limiter: Option<FrameRateLimiter>, - frame_timer: FrameTimer, +use std::time::Duration; +use winit::{event::*, event_loop::{EventLoop, ControlFlow}, window::WindowId}; + +pub struct WindowManager { event_loop: EventLoop<()>, windows: HashMap<WindowId, Window>, - program: P, + min_frame_duration: Duration, } -impl WindowManager<DefaultProgramController> { - pub fn without_program() -> Self { - Self::with_program(DefaultProgramController {}) - } -} - -impl<P: 'static + ProgramController> WindowManager<P> { - pub fn with_program(program: P) -> Self { +impl WindowManager { + pub fn new(min_frame_duration: Duration) -> Self { Self { - limiter: None, - frame_timer: FrameTimer::one_second(), event_loop: EventLoop::new(), windows: HashMap::new(), - program, + min_frame_duration, } } - pub fn with_frame_limit(mut self, limit: usize) -> Self { - self.limiter = Some(FrameRateLimiter::from_frame_rate(limit)); self - } - - /// Used to create one or more windows before the event loop starts. - pub fn create_window(&mut self, controller: Box<dyn WindowController>) { - let window = unsafe { Window::new(&self.event_loop, controller) }; + /// Add a window to the window manager before the event loop begins. + pub fn add_window(&mut self, controller: Box<dyn WindowController>) { + let window = Window::new(&self.event_loop, controller); self.windows.insert(window.id(), window); } - /// Starts the event loop, causing program control to be passed permanently to the window manager. + /// Start the event loop, passing program control to the window manager. pub fn run(mut self) -> ! { - self.event_loop.run(move |event, window_target, control_flow| { - control_flow.set_poll(); - + self.event_loop.run(move |event, _window_target, control_flow| { match event { - // Event loop has just initialised (is only ever emitted once) - Event::NewEvents(StartCause::Init) => self.program.initialise(), + // Called when the event loop is first initialized. + Event::NewEvents(StartCause::Init) => (), + + Event::NewEvents(_) => { + control_flow.set_wait_timeout(self.min_frame_duration); + } + + // Called when an application suspends on a mobile platform. + Event::Suspended => (), + + // Called when an application resumes, or after initialization on non-mobile platforms. + Event::Resumed => (), Event::WindowEvent { window_id, event } => { if let Some(window) = self.windows.get_mut(&window_id) { use WindowEvent::*; + match event { - Resized(dim) => window.resize_buffer(Dimensions::new(dim.width, dim.height)), - Moved(p) => window.controller.on_move(Point::new(p.x, p.y)), - Focused(state) => window.controller.on_focus_change(state), - - CursorEntered { .. } => window.controller.on_mouse_enter(), - CursorLeft { .. } => window.controller.on_mouse_exit(), - CursorMoved { position, .. } => { - let point = Point::new(position.x as i32, position.y as i32); - window.move_mouse(point); - } - MouseWheel {delta, ..} => { - match delta { - MouseScrollDelta::LineDelta(x, y) => { - let (x, y) = (x as f64, y as f64); - if x != 0.0 {window.controller.on_line_scroll_horizontal(x)} - if y != 0.0 {window.controller.on_line_scroll_vertical(y)} - } - MouseScrollDelta::PixelDelta(point) => { - let (x, y) = (point.x, point.y); - if x != 0.0 {window.controller.on_pixel_scroll_horizontal(x)} - if y != 0.0 {window.controller.on_pixel_scroll_vertical(y)} - } + Resized(dim) => window.resize(Dimensions::new(dim.width, dim.height)), + Moved(position) => window.controller.on_move(Point::new(position.x, position.y)), + Focused(is_focused) => window.controller.on_focus_change(is_focused), + + CursorEntered { .. } => window.controller.on_cursor_enter(), + CursorLeft { .. } => window.controller.on_cursor_exit(), + CursorMoved { position: p, .. } => { window.move_cursor(Point::new(p.x as i32, p.y as i32)) } + + MouseWheel {delta, ..} => match delta { + MouseScrollDelta::LineDelta(x, y) => { + let (x, y) = (x as f64, y as f64); + if x != 0.0 {window.controller.on_line_scroll_horizontal(x)} + if y != 0.0 {window.controller.on_line_scroll_vertical(y)} } - }, - MouseInput { state, button, .. } => { - match button { - MouseButton::Left => window.controller.on_left_mouse_button(state.into()), - MouseButton::Middle => window.controller.on_middle_mouse_button(state.into()), - MouseButton::Right => window.controller.on_right_mouse_button(state.into()), - _ => (), + MouseScrollDelta::PixelDelta(point) => { + let (x, y) = (point.x, point.y); + if x != 0.0 {window.controller.on_pixel_scroll_horizontal(x)} + if y != 0.0 {window.controller.on_pixel_scroll_vertical(y)} } - window.bump_mouse(); - + } + MouseInput { state, button, .. } => match button { + MouseButton::Left => window.controller.on_left_mouse_button(state.into()), + MouseButton::Middle => window.controller.on_middle_mouse_button(state.into()), + MouseButton::Right => window.controller.on_right_mouse_button(state.into()), + MouseButton::Other(_) => (), } - KeyboardInput { input, .. } => window.controller.on_keyboard_input(input.into()), + KeyboardInput { input, .. } => if let Ok(input) = input.try_into() { window.controller.on_keyboard_input(input)}, ModifiersChanged(state) => window.controller.on_keyboard_modifier_change(state), - ReceivedCharacter(c) => window.controller.on_character_received(c), - HoveredFile(path) => window.controller.on_file_hovered(path), - DroppedFile(path) => window.controller.on_file_dropped(path), - - // Tell the window, and let it raise its own event to close itself - // When all windows are closed: control_flow.set_exit_with_code(0); - CloseRequested => todo!("window.controller.on_close_requested()"), - _ => (), + ReceivedCharacter(character) => window.controller.on_character_input(character), + HoveredFile(path) => window.controller.on_file_hover(path), + HoveredFileCancelled => window.controller.on_file_hover_cancel(), + DroppedFile(path) => window.controller.on_file_drop(path), + + CloseRequested => { + window.controller.on_close_request(); + *control_flow = ControlFlow::Exit; + }, + Destroyed => window.controller.on_close(), + + Ime(_) => (), + AxisMotion { .. } => (), + Touch(_) => (), + TouchpadRotate { .. } => (), + TouchpadPressure { .. } => (), + TouchpadMagnify { .. } => (), + SmartMagnify { .. } => (), + ScaleFactorChanged { .. } => (), + ThemeChanged(_) => (), + Occluded(_) => (), } } } - // Called each loop before any rendering would begin. + // Called before any render events are called. Event::MainEventsCleared => { - self.frame_timer.tick(); - // println!("{}", self.frame_timer.frame_rate()); - - self.program.on_process(&mut |controller: Box<dyn WindowController>| { - let window = unsafe { Window::new(window_target, controller) }; - self.windows.insert(window.id(), window); - }); for window in self.windows.values_mut() { window.controller.on_process(); - let cursor_icon = window.controller.cursor_icon(); - window.set_cursor_icon(cursor_icon); - // let resizable = window.controller.resizable(); - // window.set_resizable(resizable); - // let cursor_visible = window.controller.cursor_visible(); - // window.set_cursor_visible(cursor_visible); - window.check_render_request(); - let title = window.controller.title(); - window.set_title(&title); - let minimum_dimensions = window.controller.minimum_dimensions(); - window.set_minimum_dimensions(minimum_dimensions); - let maximum_dimensions = window.controller.maximum_dimensions(); - window.set_maximum_dimensions(maximum_dimensions); + window.update_title(); + window.update_minimum_size(); + window.update_maximum_size(); + window.update_resizable(); + window.update_cursor_icon(); + window.update_cursor_visible(); + window.handle_render_request(); } } - // Called if a render was requested for a window + + // Called if a window has requested to be rendered. Event::RedrawRequested(window_id) => { if let Some(window) = self.windows.get_mut(&window_id) { window.render(); } } - // Called after rendering has completed - Event::RedrawEventsCleared => { - if let Some(limiter) = &mut self.limiter { - limiter.tick(); - } - } - _other => {} // todo!("{:?}", other), + // Called after all rendering has completed, or if there were no render requests. + Event::RedrawEventsCleared => (), + + // Called before the program closes. + Event::LoopDestroyed => (), + + _ => (), } }) } } - -impl Default for WindowManager<DefaultProgramController> { - fn default() -> Self { - Self::without_program() - } -} |