diff --git a/Cargo.lock b/Cargo.lock index 5675de93..6beb4090 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -239,7 +239,7 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "background_hang_monitor" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "background_hang_monitor_api", "backtrace", @@ -257,7 +257,7 @@ dependencies = [ [[package]] name = "background_hang_monitor_api" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "base", "ipc-channel", @@ -288,7 +288,7 @@ dependencies = [ [[package]] name = "base" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "crossbeam-channel", "ipc-channel", @@ -419,7 +419,7 @@ dependencies = [ [[package]] name = "bluetooth" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "bitflags 2.6.0", "bluetooth_traits", @@ -435,7 +435,7 @@ dependencies = [ [[package]] name = "bluetooth_traits" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "embedder_traits", "ipc-channel", @@ -559,7 +559,7 @@ dependencies = [ [[package]] name = "canvas" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "app_units", "bitflags 2.6.0", @@ -598,7 +598,7 @@ dependencies = [ [[package]] name = "canvas_traits" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "base", "crossbeam-channel", @@ -793,7 +793,7 @@ dependencies = [ [[package]] name = "compositing_traits" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "base", "crossbeam-channel", @@ -823,7 +823,7 @@ dependencies = [ [[package]] name = "constellation" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "background_hang_monitor", "background_hang_monitor_api", @@ -1139,7 +1139,7 @@ dependencies = [ [[package]] name = "deny_public_fields" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "syn 2.0.72", "synstructure", @@ -1158,7 +1158,7 @@ dependencies = [ [[package]] name = "derive_common" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "darling", "proc-macro2", @@ -1181,7 +1181,7 @@ dependencies = [ [[package]] name = "devtools" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "base", "chrono", @@ -1203,7 +1203,7 @@ dependencies = [ [[package]] name = "devtools_traits" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "base", "bitflags 2.6.0", @@ -1322,7 +1322,7 @@ dependencies = [ [[package]] name = "dom" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "bitflags 2.6.0", ] @@ -1330,7 +1330,7 @@ dependencies = [ [[package]] name = "dom_struct" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "quote", "syn 2.0.72", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "domobject_derive" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "proc-macro2", "quote", @@ -1390,7 +1390,7 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "embedder_traits" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "base", "cfg-if", @@ -1573,9 +1573,9 @@ checksum = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "miniz_oxide", @@ -1630,7 +1630,7 @@ dependencies = [ [[package]] name = "fonts" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "app_units", "atomic_refcell", @@ -1682,7 +1682,7 @@ dependencies = [ [[package]] name = "fonts_traits" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "ipc-channel", "malloc_size_of", @@ -2258,7 +2258,7 @@ dependencies = [ [[package]] name = "hyper_serde" version = "0.13.2" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "cookie 0.18.1", "headers", @@ -2906,7 +2906,7 @@ dependencies = [ [[package]] name = "jstraceable_derive" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "proc-macro2", "syn 2.0.72", @@ -2944,7 +2944,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "layout_2020" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "app_units", "atomic_refcell", @@ -2989,7 +2989,7 @@ dependencies = [ [[package]] name = "layout_thread_2020" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "app_units", "base", @@ -3185,7 +3185,7 @@ dependencies = [ [[package]] name = "malloc_size_of" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "accountable-refcell", "app_units", @@ -3248,7 +3248,7 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "media" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "euclid", "fnv", @@ -3309,7 +3309,7 @@ dependencies = [ [[package]] name = "metrics" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "base", "fonts_traits", @@ -3477,7 +3477,7 @@ dependencies = [ [[package]] name = "net" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "async-recursion", "async-tungstenite", @@ -3539,7 +3539,7 @@ dependencies = [ [[package]] name = "net_traits" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "base", "content-security-policy", @@ -3949,7 +3949,7 @@ dependencies = [ [[package]] name = "peek-poke" version = "0.3.0" -source = "git+https://github.com/servo/webrender?branch=0.64#9d354adf8955b1390dd56db89e6d5a9ea7880391" +source = "git+https://github.com/servo/webrender?branch=0.65#c0bcdd024adac1297ceb2f34a2de46731243c970" dependencies = [ "euclid", "peek-poke-derive", @@ -3958,7 +3958,7 @@ dependencies = [ [[package]] name = "peek-poke-derive" version = "0.3.0" -source = "git+https://github.com/servo/webrender?branch=0.64#9d354adf8955b1390dd56db89e6d5a9ea7880391" +source = "git+https://github.com/servo/webrender?branch=0.65#c0bcdd024adac1297ceb2f34a2de46731243c970" dependencies = [ "proc-macro2", "quote", @@ -4098,7 +4098,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pixels" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "euclid", "image 0.24.9", @@ -4163,12 +4163,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2288c0e17cc8d342c712bb43a257a80ebffce59cdb33d5000d8348f3ec02528b" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ "zerocopy", - "zerocopy-derive", ] [[package]] @@ -4198,7 +4197,7 @@ dependencies = [ [[package]] name = "profile" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "ipc-channel", "libc", @@ -4214,7 +4213,7 @@ dependencies = [ [[package]] name = "profile_traits" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "crossbeam-channel", "ipc-channel", @@ -4300,7 +4299,7 @@ dependencies = [ [[package]] name = "range" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "malloc_size_of", "malloc_size_of_derive", @@ -4567,9 +4566,9 @@ dependencies = [ [[package]] name = "scc" -version = "2.1.7" +version = "2.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a870e34715d5d59c8536040d4d4e7a41af44d527dc50237036ba4090db7996fc" +checksum = "8d777f59627453628a9a5be1ee8d948745b94b1dfc2d0c3099cbd9e08ab89e7c" dependencies = [ "sdd", ] @@ -4589,7 +4588,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "script" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "app_units", "arrayvec", @@ -4692,7 +4691,7 @@ dependencies = [ [[package]] name = "script_layout_interface" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "app_units", "atomic_refcell", @@ -4727,7 +4726,7 @@ dependencies = [ [[package]] name = "script_traits" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "background_hang_monitor_api", "base", @@ -4798,7 +4797,7 @@ checksum = "177258b64c0faaa9ffd3c65cd3262c2bc7e2588dbbd9c1641d0346145c1bbda8" [[package]] name = "selectors" version = "0.24.0" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "bitflags 2.6.0", "cssparser", @@ -5011,7 +5010,7 @@ dependencies = [ [[package]] name = "servo_allocator" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "libc", "tikv-jemalloc-sys", @@ -5022,7 +5021,7 @@ dependencies = [ [[package]] name = "servo_arc" version = "0.2.0" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "serde", "stable_deref_trait", @@ -5031,7 +5030,7 @@ dependencies = [ [[package]] name = "servo_atoms" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "string_cache", "string_cache_codegen", @@ -5040,7 +5039,7 @@ dependencies = [ [[package]] name = "servo_config" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "dirs-next", "embedder_traits", @@ -5061,7 +5060,7 @@ dependencies = [ [[package]] name = "servo_config_plugins" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "itertools 0.13.0", "proc-macro2", @@ -5072,7 +5071,7 @@ dependencies = [ [[package]] name = "servo_geometry" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "app_units", "euclid", @@ -5084,7 +5083,7 @@ dependencies = [ [[package]] name = "servo_rand" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "lazy_static", "log", @@ -5097,7 +5096,7 @@ dependencies = [ [[package]] name = "servo_url" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "malloc_size_of", "malloc_size_of_derive", @@ -5169,7 +5168,7 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "size_of_test" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "static_assertions", ] @@ -5299,7 +5298,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "static_prefs" version = "0.1.0" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" [[package]] name = "strck" @@ -5352,7 +5351,7 @@ dependencies = [ [[package]] name = "style" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "app_units", "arrayvec", @@ -5411,7 +5410,7 @@ dependencies = [ [[package]] name = "style_config" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "lazy_static", ] @@ -5419,7 +5418,7 @@ dependencies = [ [[package]] name = "style_derive" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "darling", "derive_common", @@ -5432,7 +5431,7 @@ dependencies = [ [[package]] name = "style_traits" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "app_units", "bitflags 2.6.0", @@ -5557,19 +5556,20 @@ dependencies = [ [[package]] name = "task_info" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "cc", ] [[package]] name = "tempfile" -version = "3.10.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", "windows-sys 0.52.0", ] @@ -5740,7 +5740,7 @@ dependencies = [ [[package]] name = "to_shmem" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "cssparser", "servo_arc", @@ -5753,7 +5753,7 @@ dependencies = [ [[package]] name = "to_shmem_derive" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74" +source = "git+https://github.com/servo/stylo?branch=2024-07-16#e7ea820c1aaee5a40f95552477c22b48b04c21b4" dependencies = [ "darling", "derive_common", @@ -5896,9 +5896,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "ttf-parser" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8686b91785aff82828ed725225925b33b4fde44c4bb15876e5f7c832724c420a" +checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" [[package]] name = "tungstenite" @@ -6422,7 +6422,7 @@ dependencies = [ [[package]] name = "webdriver_server" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "base", "base64", @@ -6450,7 +6450,7 @@ dependencies = [ [[package]] name = "webgpu" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "arrayvec", "base", @@ -6476,8 +6476,8 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webrender" -version = "0.64.0" -source = "git+https://github.com/servo/webrender?branch=0.64#9d354adf8955b1390dd56db89e6d5a9ea7880391" +version = "0.65.0" +source = "git+https://github.com/servo/webrender?branch=0.65#c0bcdd024adac1297ceb2f34a2de46731243c970" dependencies = [ "bincode", "bitflags 2.6.0", @@ -6511,8 +6511,8 @@ dependencies = [ [[package]] name = "webrender_api" -version = "0.64.0" -source = "git+https://github.com/servo/webrender?branch=0.64#9d354adf8955b1390dd56db89e6d5a9ea7880391" +version = "0.65.0" +source = "git+https://github.com/servo/webrender?branch=0.65#c0bcdd024adac1297ceb2f34a2de46731243c970" dependencies = [ "app_units", "bitflags 2.6.0", @@ -6531,7 +6531,7 @@ dependencies = [ [[package]] name = "webrender_build" version = "0.0.2" -source = "git+https://github.com/servo/webrender?branch=0.64#9d354adf8955b1390dd56db89e6d5a9ea7880391" +source = "git+https://github.com/servo/webrender?branch=0.65#c0bcdd024adac1297ceb2f34a2de46731243c970" dependencies = [ "bitflags 2.6.0", "lazy_static", @@ -6540,7 +6540,7 @@ dependencies = [ [[package]] name = "webrender_traits" version = "0.0.1" -source = "git+https://github.com/servo/servo.git?rev=5e59988#5e59988c87c40e84b0228021798455175699e824" +source = "git+https://github.com/servo/servo.git?rev=28430ba#28430bad0e7a4d4c11710d61fbaf1c598bffa87d" dependencies = [ "base", "crossbeam-channel", @@ -6693,9 +6693,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys 0.52.0", ] @@ -7063,7 +7063,7 @@ dependencies = [ [[package]] name = "wr_glyph_rasterizer" version = "0.1.0" -source = "git+https://github.com/servo/webrender?branch=0.64#9d354adf8955b1390dd56db89e6d5a9ea7880391" +source = "git+https://github.com/servo/webrender?branch=0.65#c0bcdd024adac1297ceb2f34a2de46731243c970" dependencies = [ "core-foundation", "core-graphics", @@ -7087,8 +7087,8 @@ dependencies = [ [[package]] name = "wr_malloc_size_of" -version = "0.0.2" -source = "git+https://github.com/servo/webrender?branch=0.64#9d354adf8955b1390dd56db89e6d5a9ea7880391" +version = "0.0.3" +source = "git+https://github.com/servo/webrender?branch=0.65#c0bcdd024adac1297ceb2f34a2de46731243c970" dependencies = [ "app_units", "euclid", @@ -7195,9 +7195,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" +checksum = "539a77ee7c0de333dcc6da69b177380a0b81e0dacfa4f7344c465a36871ee601" [[package]] name = "xml5ever" diff --git a/Cargo.toml b/Cargo.toml index d91d6b59..58de82fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,36 +62,35 @@ surfman = { version = "0.9", features = ["chains", "sm-raw-window-handle-05"] } thiserror = "1.0" winit = { version = "0.29", features = ["rwh_05"] } # Servo repo crates -# libservo = { git = "https://github.com/servo/servo.git", rev = "5e59988", features = ["max_log_level", "native-bluetooth", "webdriver"] } -base = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -bluetooth = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -bluetooth_traits = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -canvas = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -compositing_traits = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -constellation = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -devtools = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -embedder_traits = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -fonts = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -layout_thread_2020 = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -media = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -net = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -profile = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -profile_traits = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -script = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -script_traits = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -servo_config = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -servo_geometry = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -servo_url = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -webdriver_server = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -webrender_traits = { git = "https://github.com/servo/servo.git", rev = "5e59988" } -webgpu = { git = "https://github.com/servo/servo.git", rev = "5e59988" } +base = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +bluetooth = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +bluetooth_traits = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +canvas = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +compositing_traits = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +constellation = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +devtools = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +embedder_traits = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +fonts = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +layout_thread_2020 = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +media = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +net = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +profile = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +profile_traits = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +script = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +script_traits = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +servo_config = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +servo_geometry = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +servo_url = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +webdriver_server = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +webrender_traits = { git = "https://github.com/servo/servo.git", rev = "28430ba" } +webgpu = { git = "https://github.com/servo/servo.git", rev = "28430ba" } # Servo org crates servo-media = { git = "https://github.com/servo/media" } servo-media-dummy = { git = "https://github.com/servo/media" } style = { git = "https://github.com/servo/stylo", branch = "2024-07-16", features = ["servo"] } style_traits = { git = "https://github.com/servo/stylo", branch = "2024-07-16", features = ["servo"] } -webrender = { git = "https://github.com/servo/webrender", branch = "0.64", features = ["capture"] } -webrender_api = { git = "https://github.com/servo/webrender", branch = "0.64" } +webrender = { git = "https://github.com/servo/webrender", branch = "0.65", features = ["capture"] } +webrender_api = { git = "https://github.com/servo/webrender", branch = "0.65" } webxr = { git = "https://github.com/servo/webxr", features = ["headless"] } # Packager feature cargo-packager-resource-resolver = { version = "0.1.1", features = [ diff --git a/src/compositor.rs b/src/compositor.rs index 5247e232..577bda46 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -24,6 +24,7 @@ use script_traits::{ }; use servo_geometry::DeviceIndependentPixel; use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor}; +use surfman::Surface; use webrender::{RenderApi, Transaction}; use webrender_api::units::{ DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePoint, LayoutPoint, LayoutRect, LayoutSize, @@ -41,6 +42,7 @@ use webrender_traits::{ NetToCompositorMsg, RenderingContext, ScriptToCompositorMsg, SerializedImageUpdate, UntrustedNodeAddress, }; +use winit::window::WindowId; use crate::touch::{TouchAction, TouchHandler}; use crate::webview::WebView; @@ -98,20 +100,38 @@ pub enum MouseWindowEvent { const MAX_ZOOM: f32 = 8.0; const MIN_ZOOM: f32 = 0.1; -/// NB: Never block on the constellation, because sometimes the constellation blocks on us. +// NB: Never block on the Constellation, because sometimes the Constellation blocks on us. +/// The Verso compositor contains a GL rendering context with a WebRender instance. +/// The compositor will communicate with Servo using messages from the Constellation, +/// then composite the WebRender frames and present the surface to the window. pub struct IOCompositor { + /// All surfaces that Compositor currently owns. + pub surfaces: HashMap>, + + /// The current window that Compositor is handling. + pub current_window: WindowId, + /// Size of current viewport that Compositor is handling. viewport: DeviceIntSize, + /// The pixel density of the display. + scale_factor: Scale, + + /// The order to paint webviews in, top most webview should be the last element. + painting_order: Vec, + + /// The active webrender document. + webrender_document: DocumentId, + /// The port on which we receive messages. port: CompositorReceiver, + /// Tracks each webview and its current pipeline + webviews: HashMap, + /// Tracks details about each active pipeline that the compositor knows about. pipeline_details: HashMap, - /// The pixel density of the display. - scale_factor: Scale, - /// "Mobile-style" zoom that does not reflow the page. viewport_zoom: PinchZoomFactor, @@ -157,14 +177,11 @@ pub struct IOCompositor { /// The webrender renderer. webrender: webrender::Renderer, - /// The active webrender document. - webrender_document: DocumentId, - /// The webrender interface, if enabled. - webrender_api: RenderApi, + pub webrender_api: RenderApi, /// The surfman instance that webrender targets - rendering_context: RenderingContext, + pub rendering_context: RenderingContext, /// The GL bindings for webrender webrender_gl: Rc, @@ -194,9 +211,6 @@ pub struct IOCompositor { /// The number of frames pending to receive from WebRender. pending_frames: usize, - /// Waiting for external code to call present. - waiting_on_present: bool, - /// The [`Instant`] of the last animation tick, used to avoid flooding the Constellation and /// ScriptThread with a deluge of animation ticks. last_animation_tick: Instant, @@ -206,9 +220,6 @@ pub struct IOCompositor { /// will want to avoid blocking on UI events, and just /// run the event loop at the vsync interval. pub is_animating: bool, - - /// The order to paint webviews in, top most webview should be the last element. - painting_order: Vec, } #[derive(Clone, Copy)] @@ -334,15 +345,21 @@ impl PipelineDetails { impl IOCompositor { /// Create a new compositor. pub fn new( + current_window: WindowId, viewport: DeviceIntSize, scale_factor: Scale, state: InitialCompositorState, exit_after_load: bool, convert_mouse_to_touch: bool, ) -> Self { + let mut surfaces = HashMap::new(); + surfaces.insert(current_window, None); let compositor = IOCompositor { + surfaces, + current_window, viewport, port: state.receiver, + webviews: HashMap::new(), pipeline_details: HashMap::new(), scale_factor, composition_request: CompositionRequest::NoCompositingNecessary, @@ -371,7 +388,6 @@ impl IOCompositor { exit_after_load, convert_mouse_to_touch, pending_frames: 0, - waiting_on_present: false, last_animation_tick: Instant::now(), is_animating: false, painting_order: vec![], @@ -383,11 +399,15 @@ impl IOCompositor { } /// Consume compositor itself and deinit webrender. - pub fn deinit(self) { - // TODO: can we do this in drop? + pub fn deinit(mut self) { if let Err(err) = self.rendering_context.make_gl_context_current() { warn!("Failed to make GL context current: {:?}", err); } + for surface in self.surfaces.values_mut() { + surface + .take() + .map(|s| self.rendering_context.destroy_surface(s)); + } self.webrender.deinit(); } @@ -466,7 +486,11 @@ impl IOCompositor { } } - fn handle_browser_message(&mut self, msg: CompositorMsg, window: &mut Window) -> bool { + fn handle_browser_message( + &mut self, + msg: CompositorMsg, + windows: &mut HashMap, + ) -> bool { match self.shutdown_state { ShutdownState::NotShuttingDown => {} ShutdownState::ShuttingDown => { @@ -490,12 +514,12 @@ impl IOCompositor { } CompositorMsg::CreateOrUpdateWebView(frame_tree) => { - self.create_or_update_webview(&frame_tree, window); + self.create_or_update_webview(&frame_tree); self.send_scroll_positions_to_layout_for_pipeline(&frame_tree.pipeline.id); } CompositorMsg::RemoveWebView(top_level_browsing_context_id) => { - self.remove_webview(top_level_browsing_context_id, window); + self.remove_webview(top_level_browsing_context_id, windows); } CompositorMsg::MoveResizeWebView(_webview_id, _rect) => { @@ -1024,7 +1048,7 @@ impl IOCompositor { // Every display list needs a pipeline, but we'd like to choose one that is unlikely // to conflict with our content pipelines, which start at (1, 1). (0, 0) is WebRender's // dummy pipeline, so we choose (0, 1). - let root_pipeline = WebRenderPipelineId(0, 1); + let root_pipeline = WebRenderPipelineId(u64::from(self.current_window) as u32, 1); transaction.set_root_pipeline(root_pipeline); let mut builder = webrender::api::DisplayListBuilder::new(root_pipeline); @@ -1052,7 +1076,7 @@ impl IOCompositor { let root_clip_id = builder.define_clip_rect(zoom_reference_frame, scaled_viewport_rect); let clip_chain_id = builder.define_clip_chain(None, [root_clip_id]); for webview in &self.painting_order { - if let Some(pipeline_id) = webview.pipeline_id { + if let Some((pipeline_id, true)) = self.webviews.get(&webview.webview_id) { let scaled_webview_rect = webview.rect.to_f32() / zoom_factor; builder.push_iframe( LayoutRect::from_untyped(&scaled_webview_rect.to_untyped()), @@ -1103,14 +1127,26 @@ impl IOCompositor { } } - fn create_or_update_webview(&mut self, frame_tree: &SendableFrameTree, window: &mut Window) { - debug!("{}: Setting frame tree for webview", frame_tree.pipeline.id); + /// Set the webview of the compositor to completely loaded, and hence it could add to display + /// list. + pub fn set_webview_loaded(&mut self, webview_id: &TopLevelBrowsingContextId) { + if let Some((_, loaded)) = self.webviews.get_mut(webview_id) { + *loaded = true; + } else { + warn!("The compositor doesn't have {webview_id} to set its loaded state"); + } + } - window.set_webview( - frame_tree.pipeline.top_level_browsing_context_id, - frame_tree.pipeline.id, - self, + fn create_or_update_webview(&mut self, frame_tree: &SendableFrameTree) { + let pipeline_id = frame_tree.pipeline.id; + let webview_id = frame_tree.pipeline.top_level_browsing_context_id; + debug!( + "Verso Compositor is setting frame tree with pipeline {} for webview {}", + pipeline_id, webview_id ); + if let Some((old_pipeline, _)) = self.webviews.insert(webview_id, (pipeline_id, false)) { + debug!("{webview_id}'s pipeline has changed from {old_pipeline} to {pipeline_id}"); + } self.send_root_pipeline_display_list(); self.create_or_update_pipeline_details_with_frame_tree(frame_tree, None); @@ -1122,20 +1158,34 @@ impl IOCompositor { fn remove_webview( &mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, - window: &mut Window, + windows: &mut HashMap, ) { - debug!("{}: Removing", top_level_browsing_context_id); - let Some(webview) = window.remove_webview(top_level_browsing_context_id, self) else { - warn!("{top_level_browsing_context_id}: Removing unknown webview"); - return; - }; + debug!( + "Verso Compositor is removing webview {}", + top_level_browsing_context_id + ); + let mut window_id = None; + for window in windows.values_mut() { + let (webview, close_window) = + window.remove_webview(top_level_browsing_context_id, self); + if let Some(webview) = webview { + self.set_painting_order(window); + if let Some((pipeline_id, _)) = self.webviews.remove(&webview.webview_id) { + self.remove_pipeline_details_recursively(pipeline_id); + } - self.send_root_pipeline_display_list(); - if let Some(pipeline_id) = webview.pipeline_id { - self.remove_pipeline_details_recursively(pipeline_id); + if close_window { + window_id = Some(window.id()); + } + + self.frame_tree_id.next(); + break; + } } - self.frame_tree_id.next(); + if let Some(id) = window_id { + windows.remove(&id); + } } /// Notify compositor the provided webview is resized. The compositor will tell constellation and update the display list. @@ -1145,7 +1195,6 @@ impl IOCompositor { rect: DeviceIntRect, ) { self.send_window_size_message_for_top_level_browser_context(rect, webview_id); - self.send_root_pipeline_display_list(); } fn send_window_size_message_for_top_level_browser_context( @@ -1230,6 +1279,28 @@ impl IOCompositor { self.pipeline_details.remove(&pipeline_id); } + /// Change the current window of the compositor should display. + pub fn swap_current_window(&mut self, window: &mut Window) { + if window.id() != self.current_window { + debug!( + "Verso Compositor swap current window from {:?} to {:?}", + self.current_window, + window.id() + ); + if let Some(Some(new_surface)) = self.surfaces.insert(window.id(), None) { + // Swap the surface + self.rendering_context.with_front_buffer(|_, old_surface| { + self.surfaces.insert(self.current_window, Some(old_surface)); + new_surface + }); + self.current_window = window.id(); + self.scale_factor = Scale::new(window.scale_factor() as f32); + self.painting_order.clear(); + window.resize(window.size(), self); + } + } + } + /// Handle the window resize event and return a boolean to tell embedder if it should further /// handle the resize event. pub fn on_resize_window_event(&mut self, new_viewport: DeviceIntSize) -> bool { @@ -1243,6 +1314,18 @@ impl IOCompositor { transaction.set_document_view(DeviceIntRect::from_size(self.viewport)); self.webrender_api .send_transaction(self.webrender_document, transaction); + self.composite_if_necessary(CompositingReason::Resize); + true + } + + /// Handle the window scale factor event and return a boolean to tell embedder if it should further + /// handle the scale factor event. + pub fn on_scale_factor_event(&mut self, scale_factor: f32) -> bool { + if self.shutdown_state != ShutdownState::NotShuttingDown { + return false; + } + + self.scale_factor = Scale::new(scale_factor); self.update_after_zoom_or_hidpi_change(); self.composite_if_necessary(CompositingReason::Resize); true @@ -1486,7 +1569,7 @@ impl IOCompositor { self.dispatch_mouse_window_event_class(MouseWindowEvent::Click(button, p)); } - /// Hit test and foward the wheel event to constellation. + /// Hit test and forward the wheel event to constellation. pub fn on_wheel_event(&mut self, delta: WheelDelta, p: DevicePoint) { if self.shutdown_state != ShutdownState::NotShuttingDown { return; @@ -1712,10 +1795,6 @@ impl IOCompositor { } } - fn scale_factor(&self) -> Scale { - self.scale_factor - } - fn device_pixels_per_page_pixel(&self) -> Scale { self.device_pixels_per_page_pixel_not_including_page_zoom() * self.pinch_zoom_level() } @@ -1723,7 +1802,7 @@ impl IOCompositor { fn device_pixels_per_page_pixel_not_including_page_zoom( &self, ) -> Scale { - self.page_zoom * self.scale_factor() + self.page_zoom * self.scale_factor } /// Handle zoom reset event @@ -1884,13 +1963,6 @@ impl IOCompositor { /// Composite to the given target if any, or the current target otherwise. fn composite_specific_target(&mut self) -> Result<(), UnableToComposite> { - if self.waiting_on_present { - debug!("tried to composite while waiting on present"); - return Err(UnableToComposite::NotReadyToPaintImage( - NotReadyToPaint::WaitingOnConstellation, - )); - } - if let Err(err) = self.rendering_context.make_gl_context_current() { warn!("Failed to make GL context current: {:?}", err); } @@ -1934,10 +2006,9 @@ impl IOCompositor { trace!("Compositing"); // Paint the scene. // TODO(gw): Take notice of any errors the renderer returns! - self.clear_background(); self.webrender // TODO to untyped? - .render(self.viewport, 0 /* buffer_age */) + .render(self.viewport, 0) .ok(); }, ); @@ -1988,15 +2059,9 @@ impl IOCompositor { } } - // Notify embedder that servo is ready to present. - // Embedder should call `present` to tell compositor to continue rendering. - self.waiting_on_present = true; - let webview_ids = self.painting_order.iter().map(|w| w.webview_id); - let msg = ConstellationMsg::ReadyToPresent(webview_ids.collect()); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending event to constellation failed ({:?}).", e); + if let Err(err) = self.rendering_context.present() { + warn!("Failed to present surface: {:?}", err); } - self.composition_request = CompositionRequest::NoCompositingNecessary; self.process_animations(true); @@ -2004,14 +2069,6 @@ impl IOCompositor { Ok(()) } - /// Displays the contents of the surface on screen. - pub fn present(&mut self) { - if let Err(err) = self.rendering_context.present() { - warn!("Failed to present surface: {:?}", err); - } - self.waiting_on_present = false; - } - fn composite_if_necessary(&mut self, reason: CompositingReason) { trace!( "Will schedule a composite {reason:?}. Previously was {:?}", @@ -2020,44 +2077,6 @@ impl IOCompositor { self.composition_request = CompositionRequest::CompositeNow(reason) } - fn clear_background(&self) { - let gl = &self.webrender_gl; - self.assert_gl_framebuffer_complete(); - - // Set the viewport background based on prefs. - let color = servo_config::pref!(shell.background_color.rgba); - gl.clear_color( - color[0] as f32, - color[1] as f32, - color[2] as f32, - color[3] as f32, - ); - - let framebuffer_height = self.viewport.height; - // Clear the viewport rect of each top-level browsing context. - for webview in &self.painting_order { - // Flip the rectangle in the framebuffer - let origin = webview.rect.to_i32(); - let mut rect = origin.clone(); - let min_y = framebuffer_height - rect.max.y; - let max_y = framebuffer_height - rect.min.y; - rect.min.y = min_y; - rect.max.y = max_y; - - gl.scissor( - rect.min.x, - rect.min.y, - rect.size().width, - rect.size().height, - ); - gl.enable(gl::SCISSOR_TEST); - gl.clear(gl::COLOR_BUFFER_BIT); - gl.disable(gl::SCISSOR_TEST); - } - - self.assert_gl_framebuffer_complete(); - } - #[track_caller] fn assert_no_gl_error(&self) { debug_assert_eq!(self.webrender_gl.get_error(), gl::NO_ERROR); @@ -2075,7 +2094,7 @@ impl IOCompositor { } /// Receive and handle compositor messages. - pub fn receive_messages(&mut self, window: &mut Window) -> bool { + pub fn receive_messages(&mut self, windows: &mut HashMap) -> bool { // Check for new messages coming from the other threads in the system. let mut compositor_messages = vec![]; let mut found_recomposite_msg = false; @@ -2094,7 +2113,7 @@ impl IOCompositor { } } for msg in compositor_messages { - if !self.handle_browser_message(msg, window) { + if !self.handle_browser_message(msg, windows) { return false; } } @@ -2136,11 +2155,11 @@ impl IOCompositor { /// paint is not scheduled the compositor will hang forever. /// /// This is used when resizing the window. - pub fn repaint_synchronously(&mut self, window: &mut Window) { + pub fn repaint_synchronously(&mut self, windows: &mut HashMap) { while self.shutdown_state != ShutdownState::ShuttingDown { let msg = self.port.recv_compositor_msg(); let need_recomposite = matches!(msg, CompositorMsg::NewWebRenderFrameReady(_)); - let keep_going = self.handle_browser_message(msg, window); + let keep_going = self.handle_browser_message(msg, windows); if need_recomposite { self.composite(); break; @@ -2189,8 +2208,25 @@ impl IOCompositor { } /// Update the painting order of the compositor. - pub fn set_painting_order(&mut self, painting_order: Vec) { - self.painting_order = painting_order; + pub fn set_painting_order(&mut self, window: &Window) { + if self.current_window == window.id() { + let painting_order = window.painting_order(); + self.painting_order = painting_order; + self.send_root_pipeline_display_list(); + debug!( + "Verso Compositor sets painting order to {:?}'s painting order {:?}", + window.id(), + self.painting_order + .iter() + .map(|w| w.webview_id) + .collect::>() + ); + } else { + warn!( + "Failed to set painting order due to {:?} is not the current window", + window.id() + ); + } } } diff --git a/src/main.rs b/src/main.rs index f96b87ce..258f0971 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,64 +3,36 @@ use verso::config::Config; use verso::{Result, Verso}; +use winit::event::{Event, StartCause}; +use winit::event_loop::EventLoop; use winit::event_loop::{ControlFlow, DeviceEvents}; -use winit::{event_loop::EventLoop, window::WindowBuilder}; - -/* window decoration */ -#[cfg(macos)] -use cocoa::appkit::{NSWindow, NSWindowStyleMask, NSWindowTitleVisibility}; -#[cfg(macos)] -use objc::runtime::Object; -#[cfg(macos)] -use raw_window_handle::{AppKitWindowHandle, HasRawWindowHandle, RawWindowHandle}; -#[cfg(macos)] -use winit::dpi::LogicalPosition; fn main() -> Result<()> { let event_loop = EventLoop::new()?; event_loop.listen_device_events(DeviceEvents::Never); - let window = WindowBuilder::new() - // .with_decorations(false) - .build(&event_loop)?; - - #[cfg(macos)] - unsafe { - let rwh = window.raw_window_handle(); - if let RawWindowHandle::AppKit(AppKitWindowHandle { ns_window, .. }) = rwh { - decorate_window(ns_window as *mut Object, LogicalPosition::new(8.0, 40.0)); - } - } - - let config = Config::new(resources_dir_path().unwrap()); - let mut verso = Verso::new(window, event_loop.create_proxy(), config); + let proxy = event_loop.create_proxy(); + let mut verso = None; event_loop.run(move |event, evl| { - verso.run(event); - if verso.finished_shutting_down() { - evl.exit(); - } else if verso.is_animating() { - evl.set_control_flow(ControlFlow::Poll); + if let Event::NewEvents(StartCause::Init) = event { + let config = Config::new(resources_dir_path().unwrap()); + verso = Some(Verso::new(evl, proxy.clone(), config)); } else { - evl.set_control_flow(ControlFlow::Wait); + if let Some(v) = &mut verso { + v.run(event, evl); + if v.finished_shutting_down() { + evl.exit(); + } else if v.is_animating() { + evl.set_control_flow(ControlFlow::Poll); + } else { + evl.set_control_flow(ControlFlow::Wait); + } + } } })?; Ok(()) } -#[cfg(macos)] -pub unsafe fn decorate_window(window: *mut Object, _position: LogicalPosition) { - NSWindow::setTitlebarAppearsTransparent_(window, cocoa::base::YES); - NSWindow::setTitleVisibility_(window, NSWindowTitleVisibility::NSWindowTitleHidden); - NSWindow::setStyleMask_( - window, - NSWindowStyleMask::NSTitledWindowMask - | NSWindowStyleMask::NSFullSizeContentViewWindowMask - | NSWindowStyleMask::NSClosableWindowMask - | NSWindowStyleMask::NSResizableWindowMask - | NSWindowStyleMask::NSMiniaturizableWindowMask, - ); -} - fn resources_dir_path() -> Option { #[cfg(feature = "packager")] let root_dir = { diff --git a/src/verso.rs b/src/verso.rs index 2bc36b27..c1cd3614 100644 --- a/src/verso.rs +++ b/src/verso.rs @@ -1,10 +1,12 @@ use std::{ borrow::Cow, + collections::HashMap, path::PathBuf, sync::{atomic::Ordering, Arc}, }; use arboard::Clipboard; +use base::id::WebViewId; use bluetooth::BluetoothThreadFactory; use bluetooth_traits::BluetoothRequest; use canvas::{ @@ -17,7 +19,7 @@ use compositing_traits::{ use constellation::{Constellation, FromCompositorLogger, InitialConstellationState}; use crossbeam_channel::{unbounded, Sender}; use devtools; -use embedder_traits::{EmbedderProxy, EmbedderReceiver, EventLoopWaker}; +use embedder_traits::{EmbedderMsg, EmbedderProxy, EmbedderReceiver, EventLoopWaker}; use euclid::Scale; use fonts::FontCacheThread; use gleam::gl; @@ -33,25 +35,27 @@ use servo_config::{opts, pref}; use servo_url::ServoUrl; use style; use surfman::GLApi; +use units::DeviceIntRect; use webgpu; use webrender::{create_webrender_instance, ShaderPrecacheFlags, WebRenderOptions}; use webrender_api::*; use webrender_traits::*; use winit::{ - event::{Event, StartCause}, - event_loop::EventLoopProxy, - window::Window as WinitWindow, + event::{Event, WindowEvent}, + event_loop::{EventLoopProxy, EventLoopWindowTarget}, + window::WindowId, }; use crate::{ compositor::{IOCompositor, InitialCompositorState, ShutdownState}, config::Config, + webview::WebView, window::Window, }; /// Main entry point of Verso browser. pub struct Verso { - window: Window, + windows: HashMap, compositor: Option, constellation_sender: Sender, embedder_receiver: EmbedderReceiver, @@ -80,11 +84,11 @@ impl Verso { /// - Font cache /// - Canvas /// - Constellation - pub fn new(window: WinitWindow, proxy: EventLoopProxy<()>, config: Config) -> Self { + pub fn new(evl: &EventLoopWindowTarget<()>, proxy: EventLoopProxy<()>, config: Config) -> Self { // Initialize configurations and Verso window let resource_dir = config.resource_dir.clone(); config.init(); - let (window, rendering_context) = Window::new(window); + let (window, rendering_context) = Window::new(evl); let event_loop_waker = Box::new(Waker(proxy)); let opts = opts::get(); @@ -106,6 +110,7 @@ impl Verso { gl::GlesFns::load_with(|s| rendering_context.get_proc_address(s)) }, }; + // Make sure the gl context is made current. rendering_context.make_gl_context_current().unwrap(); debug_assert_eq!(webrender_gl.get_error(), gl::NO_ERROR,); @@ -162,7 +167,7 @@ impl Verso { debug_flags.set(DebugFlags::PROFILER_DBG, opts.debug.webrender_stats); let render_notifier = Box::new(RenderNotifier::new(compositor_sender.clone())); - let clear_color = ColorF::new(1., 1., 1., 0.); + let clear_color = ColorF::new(0., 0., 0., 0.); create_webrender_instance( webrender_gl.clone(), render_notifier, @@ -191,7 +196,8 @@ impl Verso { .expect("Unable to initialize webrender!") }; let webrender_api = webrender_api_sender.create_api(); - let webrender_document = webrender_api.add_document(window.size()); + let webrender_document = + webrender_api.add_document_with_id(window.size(), u64::from(window.id()) as u32); // Initialize js engine if it's single process mode let js_engine_setup = if !opts.multiprocess { @@ -336,6 +342,7 @@ impl Verso { // The compositor coordinates with the client window to create the final // rendered page and display it somewhere. let compositor = IOCompositor::new( + window.id(), window.size(), Scale::new(window.scale_factor() as f32), InitialCompositorState { @@ -355,9 +362,22 @@ impl Verso { opts.debug.convert_mouse_to_touch, ); + // Send the constellation message to start Panel UI + // TODO: Should become a window method + let panel_id = window.panel.as_ref().unwrap().webview_id; + let path = resource_dir.join("panel.html"); + let url = ServoUrl::from_file_path(path.to_str().unwrap()).unwrap(); + send_to_constellation( + &constellation_sender, + ConstellationMsg::NewWebView(url, panel_id), + ); + + let mut windows = HashMap::new(); + windows.insert(window.id(), window); + // Create Verso instance let verso = Verso { - window, + windows, compositor: Some(compositor), constellation_sender, embedder_receiver, @@ -374,67 +394,109 @@ impl Verso { /// /// - Handle Winit's event, updating Compositor and sending messages to Constellation. /// - Handle Servo's messages and updating Compositor again. - pub fn run(&mut self, event: Event<()>) { + pub fn run(&mut self, event: Event<()>, evl: &EventLoopWindowTarget<()>) { self.handle_winit_event(event); - self.handle_servo_messages(); + self.handle_servo_messages(evl); + if self.windows.is_empty() { + self.compositor + .as_mut() + .map(IOCompositor::maybe_start_shutting_down); + } } /// Handle Winit events fn handle_winit_event(&mut self, event: Event<()>) { log::trace!("Verso is handling Winit event: {event:?}"); match event { - Event::NewEvents(StartCause::Init) => { - // Send the constellation message to start Panel UI - let panel_id = self.window.panel.webview_id; - let path = self.resource_dir.join("panel.html"); - let url = ServoUrl::from_file_path(path.to_str().unwrap()).unwrap(); - send_to_constellation( - &self.constellation_sender, - ConstellationMsg::NewWebView(url, panel_id), - ); - } - Event::Suspended | Event::Resumed | Event::UserEvent(()) => {} - Event::WindowEvent { - window_id: _, - event, - } => { + Event::NewEvents(_) | Event::Suspended | Event::Resumed | Event::UserEvent(()) => {} + Event::WindowEvent { window_id, event } => { if let Some(compositor) = &mut self.compositor { - self.window.handle_winit_window_event( - &self.constellation_sender, - compositor, - &event, - ) + if let WindowEvent::CloseRequested = event { + // self.windows.remove(&window_id); + compositor.maybe_start_shutting_down(); + } else { + let mut need_repaint = false; + for (id, window) in &mut self.windows { + if window_id == *id { + need_repaint = window.handle_winit_window_event( + &self.constellation_sender, + compositor, + &event, + ); + } + } + + if need_repaint { + compositor.repaint_synchronously(&mut self.windows); + } + } } } - e => log::warn!("Verso isn't supporting this event yet: {e:?}"), + e => log::trace!("Verso isn't supporting this event yet: {e:?}"), } } /// Handle message came from Servo. - fn handle_servo_messages(&mut self) { + fn handle_servo_messages(&mut self, evl: &EventLoopWindowTarget<()>) { let mut shutdown = false; if let Some(compositor) = &mut self.compositor { // Handle Compositor's messages first log::trace!("Verso is handling Compositor messages"); - if compositor.receive_messages(&mut self.window) { + if compositor.receive_messages(&mut self.windows) { // And then handle Embedder messages log::trace!( "Verso is handling Embedder messages when shutdown state is set to {:?}", compositor.shutdown_state ); - while let Some((top_level_browsing_context, msg)) = - self.embedder_receiver.try_recv_embedder_msg() - { + while let Some((webview_id, msg)) = self.embedder_receiver.try_recv_embedder_msg() { match compositor.shutdown_state { ShutdownState::NotShuttingDown => { - // TODO we need to worry about which window to handle message in - // multiwindow - self.window.handle_servo_message( - top_level_browsing_context, - msg, - &self.constellation_sender, - self.clipboard.as_mut(), - ); + if let Some(id) = webview_id { + for window in self.windows.values_mut() { + if window.has_webview(id) { + if window.handle_servo_message( + id, + msg, + &self.constellation_sender, + self.clipboard.as_mut(), + compositor, + ) { + let mut window = + Window::new_with_compositor(evl, compositor); + let panel_id = WebViewId::new(); + let path = self.resource_dir.join("panel.html"); + let url = + ServoUrl::from_file_path(path.to_str().unwrap()) + .unwrap(); + send_to_constellation( + &self.constellation_sender, + ConstellationMsg::NewWebView(url, panel_id), + ); + let rect = DeviceIntRect::from_size(window.size()); + window.panel = Some(WebView::new(panel_id, rect)); + self.windows.insert(window.id(), window); + } + break; + } + } + } else { + // Handle message in Verso Window + log::trace!("Verso Window is handling Embedder message: {msg:?}"); + match msg { + EmbedderMsg::SetCursor(cursor) => { + // TODO: This should move to compositor + if let Some(window) = + self.windows.get(&compositor.current_window) + { + window.set_cursor_icon(cursor); + } + } + EmbedderMsg::Shutdown | EmbedderMsg::ReadyToPresent(_) => {} + e => { + log::trace!("Verso Window isn't supporting handling this message yet: {e:?}") + } + } + } } ShutdownState::FinishedShuttingDown => { log::error!("Verso shouldn't be handling messages after compositor has shut down"); diff --git a/src/webview.rs b/src/webview.rs index ffb34109..de7a1b34 100644 --- a/src/webview.rs +++ b/src/webview.rs @@ -1,5 +1,5 @@ use arboard::Clipboard; -use base::id::{PipelineId, PipelineNamespace, PipelineNamespaceId, WebViewId}; +use base::id::{PipelineNamespace, PipelineNamespaceId, WebViewId}; use compositing_traits::ConstellationMsg; use crossbeam_channel::Sender; use embedder_traits::{CompositorEventVariant, EmbedderMsg, PromptDefinition}; @@ -7,15 +7,13 @@ use script_traits::TraversalDirection; use servo_url::ServoUrl; use webrender_api::units::DeviceIntRect; -use crate::{verso::send_to_constellation, window::Window}; +use crate::{compositor::IOCompositor, verso::send_to_constellation, window::Window}; /// A web view is an area to display web browsing context. It's what user will treat as a "web page". #[derive(Debug, Clone)] pub struct WebView { /// Webview ID pub webview_id: WebViewId, - /// Pipeline ID for webrender usage. - pub pipeline_id: Option, /// The position and size of the webview. pub rect: DeviceIntRect, } @@ -23,11 +21,7 @@ pub struct WebView { impl WebView { /// Create a web view from Winit window. pub fn new(webview_id: WebViewId, rect: DeviceIntRect) -> Self { - Self { - webview_id, - pipeline_id: None, - rect, - } + Self { webview_id, rect } } /// Create a panel view from Winit window. A panel is a special web view that focus on controlling states around window. @@ -47,7 +41,6 @@ impl WebView { let id = WebViewId::new(); Self { webview_id: id, - pipeline_id: None, rect, } } @@ -61,19 +54,29 @@ impl Window { message: EmbedderMsg, sender: &Sender, clipboard: Option<&mut Clipboard>, + compositor: &mut IOCompositor, ) { log::trace!("Verso WebView {webview_id:?} is handling Embedder message: {message:?}",); match message { EmbedderMsg::LoadStart | EmbedderMsg::HeadParsed | EmbedderMsg::WebViewOpened(_) - | EmbedderMsg::WebViewClosed(_) - | EmbedderMsg::WebViewFocused(_) => { + | EmbedderMsg::WebViewClosed(_) => { // Most WebView messages are ignored because it's done by compositor. log::trace!("Verso WebView {webview_id:?} ignores this message: {message:?}") } + EmbedderMsg::WebViewFocused(w) => { + log::debug!( + "Verso Window {:?}'s webview {} has loaded completely.", + self.id(), + w + ); + compositor.set_webview_loaded(&w); + compositor.set_painting_order(self); + } EmbedderMsg::LoadComplete => { self.window.request_redraw(); + send_to_constellation(sender, ConstellationMsg::FocusWebView(webview_id)); } EmbedderMsg::AllowNavigationRequest(id, _url) => { // TODO should provide a API for users to check url @@ -114,35 +117,50 @@ impl Window { } } e => { - log::warn!("Verso WebView isn't supporting this message yet: {e:?}") + log::trace!("Verso WebView isn't supporting this message yet: {e:?}") } } } - /// Handle servo messages with main panel. + /// Handle servo messages with main panel. Return true it requests a new window. pub fn handle_servo_messages_with_panel( &mut self, panel_id: WebViewId, message: EmbedderMsg, sender: &Sender, clipboard: Option<&mut Clipboard>, - ) { + compositor: &mut IOCompositor, + ) -> bool { log::trace!("Verso Panel {panel_id:?} is handling Embedder message: {message:?}",); match message { EmbedderMsg::LoadStart | EmbedderMsg::HeadParsed | EmbedderMsg::WebViewOpened(_) - | EmbedderMsg::WebViewClosed(_) - | EmbedderMsg::WebViewFocused(_) => { + | EmbedderMsg::WebViewClosed(_) => { // Most WebView messages are ignored because it's done by compositor. log::trace!("Verso Panel ignores this message: {message:?}") } + EmbedderMsg::WebViewFocused(w) => { + log::debug!( + "Verso Window {:?}'s panel {} has loaded completely.", + self.id(), + w + ); + compositor.set_webview_loaded(&w); + compositor.set_painting_order(self); + } EmbedderMsg::LoadComplete => { self.window.request_redraw(); - // let demo_url = ServoUrl::parse("https://demo.versotile.org").unwrap(); - let demo_url = ServoUrl::parse("https://keyboard-test.space").unwrap(); + send_to_constellation(sender, ConstellationMsg::FocusWebView(panel_id)); + + let demo_url = ServoUrl::parse("https://example.com").unwrap(); let demo_id = WebViewId::new(); + let size = self.size(); + let mut rect = DeviceIntRect::from_size(size); + rect.min.y = rect.max.y.min(76); + self.webview = Some(WebView::new(demo_id, rect)); send_to_constellation(sender, ConstellationMsg::NewWebView(demo_url, demo_id)); + log::debug!("Verso Window {:?} adds webview {}", self.id(), demo_id); } EmbedderMsg::AllowNavigationRequest(id, _url) => { // The panel shouldn't navigate to other pages. @@ -154,6 +172,7 @@ impl Window { EmbedderMsg::Prompt(definition, _origin) => { match definition { PromptDefinition::Input(msg, _, prompt_sender) => { + let _ = prompt_sender.send(None); if let Some(webview) = &self.webview { let id = webview.webview_id; @@ -185,7 +204,8 @@ impl Window { // TODO Set EmbedderMsg::Status to None } "REFRESH" => { - send_to_constellation(sender, ConstellationMsg::Reload(id)); + // send_to_constellation(sender, ConstellationMsg::Reload(id)); + return true; } "MINIMIZE" => { self.window.set_minimized(true); @@ -194,15 +214,14 @@ impl Window { let is_maximized = self.window.is_maximized(); self.window.set_maximized(!is_maximized); } - e => log::warn!( + e => log::trace!( "Verso Panel isn't supporting this prompt message yet: {e}" ), } } } - let _ = prompt_sender.send(None); } - _ => log::warn!("Verso Panel isn't supporting this prompt yet"), + _ => log::trace!("Verso Panel isn't supporting this prompt yet"), } } EmbedderMsg::GetClipboardContents(sender) => { @@ -226,8 +245,9 @@ impl Window { }); } e => { - log::warn!("Verso Panel isn't supporting this message yet: {e:?}") + log::trace!("Verso Panel isn't supporting this message yet: {e:?}") } } + false } } diff --git a/src/window.rs b/src/window.rs index 0a2095e9..5a837d2a 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,13 +1,14 @@ use std::cell::Cell; -use base::id::{PipelineId, WebViewId}; +use base::id::WebViewId; use compositing_traits::ConstellationMsg; use crossbeam_channel::Sender; use embedder_traits::{Cursor, EmbedderMsg}; use euclid::{Point2D, Size2D}; use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use script_traits::{TouchEventType, WheelDelta, WheelMode}; -use surfman::{Connection, SurfaceType}; +use surfman::Connection; +use surfman::SurfaceType; use webrender_api::{ units::{ DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel, DevicePoint, LayoutVector2D, @@ -18,8 +19,9 @@ use webrender_traits::RenderingContext; use winit::{ dpi::PhysicalPosition, event::{ElementState, TouchPhase, WindowEvent}, + event_loop::EventLoopWindowTarget, keyboard::ModifiersState, - window::{CursorIcon, Window as WinitWindow}, + window::{CursorIcon, Window as WinitWindow, WindowBuilder, WindowId}, }; use crate::{ @@ -36,7 +38,7 @@ pub struct Window { /// Access to Winit window pub(crate) window: WinitWindow, /// The main control panel of this window. - pub(crate) panel: WebView, + pub(crate) panel: Option, /// The WebView of this window. pub(crate) webview: Option, /// The mouse physical position in the web view. @@ -47,7 +49,19 @@ pub struct Window { impl Window { /// Create a Verso window from Winit window and return the rendering context. - pub fn new(window: WinitWindow) -> (Self, RenderingContext) { + pub fn new(evl: &EventLoopWindowTarget<()>) -> (Self, RenderingContext) { + let window = WindowBuilder::new() + // .with_transparent(true) + // .with_decorations(false) + .build(evl) + .expect("Failed to create window."); + #[cfg(macos)] + unsafe { + let rwh = window.raw_window_handle(); + if let RawWindowHandle::AppKit(AppKitWindowHandle { ns_window, .. }) = rwh { + decorate_window(ns_window as *mut Object, LogicalPosition::new(8.0, 40.0)); + } + } let window_size = window.inner_size(); let window_size = Size2D::new(window_size.width as i32, window_size.height as i32); let display_handle = window.raw_display_handle(); @@ -69,7 +83,7 @@ impl Window { ( Self { window, - panel: WebView::new_panel(DeviceIntRect::from_size(size)), + panel: Some(WebView::new_panel(DeviceIntRect::from_size(size))), webview: None, mouse_position: Cell::new(PhysicalPosition::default()), modifiers_state: Cell::new(ModifiersState::default()), @@ -78,20 +92,67 @@ impl Window { ) } - /// Handle Winit window event. + /// Create a Verso window with the rendering context. + pub fn new_with_compositor( + evl: &EventLoopWindowTarget<()>, + compositor: &mut IOCompositor, + ) -> Self { + let window = WindowBuilder::new() + // .with_transparent(true) + // .with_decorations(false) + .build(evl) + .expect("Failed to create window."); + #[cfg(macos)] + unsafe { + let rwh = window.raw_window_handle(); + if let RawWindowHandle::AppKit(AppKitWindowHandle { ns_window, .. }) = rwh { + decorate_window(ns_window as *mut Object, LogicalPosition::new(8.0, 40.0)); + } + } + let window_size = window.inner_size(); + let window_size = Size2D::new(window_size.width as i32, window_size.height as i32); + let native_widget = compositor + .rendering_context + .connection() + .create_native_widget_from_raw_window_handle(window.raw_window_handle(), window_size) + .expect("Failed to create native widget"); + let surface_type = SurfaceType::Widget { native_widget }; + let surface = compositor + .rendering_context + .create_surface(surface_type) + .ok(); + compositor.surfaces.insert(window.id(), surface); + Self { + window, + panel: None, + webview: None, + mouse_position: Cell::new(PhysicalPosition::default()), + modifiers_state: Cell::new(ModifiersState::default()), + } + } + + /// Handle Winit window event and return a boolean to indicate if the compositor should repaint immediately. pub fn handle_winit_window_event( &mut self, sender: &Sender, compositor: &mut IOCompositor, event: &winit::event::WindowEvent, - ) { + ) -> bool { match event { - WindowEvent::RedrawRequested => { - compositor.present(); + WindowEvent::Focused(focused) => { + if *focused { + compositor.swap_current_window(self); + } } WindowEvent::Resized(size) => { let size = Size2D::new(size.width, size.height); - let _ = self.resize(size.to_i32(), compositor); + return self.resize(size.to_i32(), compositor); + } + WindowEvent::ScaleFactorChanged { scale_factor, .. } => { + compositor.on_scale_factor_event(*scale_factor as f32); + } + WindowEvent::CursorEntered { .. } => { + compositor.swap_current_window(self); } WindowEvent::CursorMoved { position, .. } => { let cursor: DevicePoint = DevicePoint::new(position.x as f32, position.y as f32); @@ -104,10 +165,10 @@ impl Window { winit::event::MouseButton::Right => script_traits::MouseButton::Right, winit::event::MouseButton::Middle => script_traits::MouseButton::Middle, _ => { - log::warn!( + log::trace!( "Verso Window isn't supporting this mouse button yet: {button:?}" ); - return; + return false; } }; let position = Point2D::new( @@ -177,9 +238,6 @@ impl Window { phase, ); } - WindowEvent::CloseRequested => { - compositor.maybe_start_shutting_down(); - } WindowEvent::ModifiersChanged(modifier) => self.modifiers_state.set(modifier.state()), WindowEvent::KeyboardInput { event, .. } => { let event = keyboard_event_from_winit(&event, self.modifiers_state.get()); @@ -187,44 +245,31 @@ impl Window { let msg = ConstellationMsg::Keyboard(event); send_to_constellation(sender, msg); } - e => log::warn!("Verso Window isn't supporting this window event yet: {e:?}"), + e => log::trace!("Verso Window isn't supporting this window event yet: {e:?}"), } + false } - /// Handle servo messages. + /// Handle servo messages. Return true if it requests a new window pub fn handle_servo_message( &mut self, - webview_id: Option, + webview_id: WebViewId, message: EmbedderMsg, sender: &Sender, clipboard: Option<&mut Clipboard>, - ) { - match webview_id { - // // Handle message in Verso Panel - Some(p) if p == self.panel.webview_id => { - self.handle_servo_messages_with_panel(p, message, sender, clipboard); - } - // Handle message in Verso WebView - Some(w) => { - self.handle_servo_messages_with_webview(w, message, sender, clipboard); - } - // Handle message in Verso Window - None => { - log::trace!("Verso Window is handling Embedder message: {message:?}"); - match message { - EmbedderMsg::ReadyToPresent(_w) => { - self.window.request_redraw(); - } - EmbedderMsg::SetCursor(cursor) => { - self.set_cursor_icon(cursor); - } - EmbedderMsg::Shutdown => {} - e => { - log::warn!("Verso Window isn't supporting handling this message yet: {e:?}") - } - } + compositor: &mut IOCompositor, + ) -> bool { + // // Handle message in Verso Panel + if let Some(panel) = &self.panel { + if panel.webview_id == webview_id { + return self.handle_servo_messages_with_panel( + webview_id, message, sender, clipboard, compositor, + ); } } + // Handle message in Verso WebView + self.handle_servo_messages_with_webview(webview_id, message, sender, clipboard, compositor); + false } /// Queues a Winit `WindowEvent::RedrawRequested` event to be emitted that aligns with the windowing system drawing loop. @@ -232,23 +277,31 @@ impl Window { self.window.request_redraw() } - /// Resize the rendering context and all web views. - pub fn resize(&mut self, size: Size2D, compositor: &mut IOCompositor) { + /// Resize the rendering context and all web views. Return true if the compositor should repaint and present + /// after this. + pub fn resize( + &mut self, + size: Size2D, + compositor: &mut IOCompositor, + ) -> bool { let need_resize = compositor.on_resize_window_event(size); - let rect = DeviceIntRect::from_size(size); - compositor.on_resize_webview_event(self.panel.webview_id, rect); + if let Some(panel) = &mut self.panel { + let rect = DeviceIntRect::from_size(size); + panel.rect = rect; + compositor.on_resize_webview_event(panel.webview_id, rect); + } - if let Some(w) = &self.webview { + if let Some(w) = &mut self.webview { let mut rect = DeviceIntRect::from_size(size); rect.min.y = rect.max.y.min(76); + w.rect = rect; compositor.on_resize_webview_event(w.webview_id, rect); } - if need_resize { - compositor.repaint_synchronously(self); - compositor.present(); - } + compositor.set_painting_order(self); + + need_resize } /// Size of the window that's used by webrender. @@ -257,51 +310,20 @@ impl Window { Size2D::new(size.width as i32, size.height as i32) } + /// Get Winit window ID of the window. + pub fn id(&self) -> WindowId { + self.window.id() + } + /// Scale factor of the window. This is also known as HIDPI. pub fn scale_factor(&self) -> f64 { self.window.scale_factor() } - /// Get the mutable reference of the webview in this window from provided webview ID. - pub fn get_webview(&mut self, id: WebViewId) -> Option<&mut WebView> { - if self.panel.webview_id == id { - Some(&mut self.panel) - } else { - self.webview.as_mut().filter(|w| w.webview_id == id) - } - } - - /// Set the webview to this window. It won't be updated if the exisitng webview and pipeline ID - /// are the same. This will also set the painting order of the compositor and tell - /// constellation to focus the webview. - pub fn set_webview( - &mut self, - webview_id: WebViewId, - pipline_id: PipelineId, - compositor: &mut IOCompositor, - ) { - if self.panel.webview_id == webview_id { - if self.panel.pipeline_id != Some(pipline_id) { - self.panel.pipeline_id = Some(pipline_id); - } - } else if let Some(webview) = &mut self.webview { - if webview.webview_id == webview_id && webview.pipeline_id != Some(pipline_id) { - webview.pipeline_id = Some(pipline_id); - } - } else { - let size = self.size(); - let mut rect = DeviceIntRect::from_size(size); - rect.min.y = rect.max.y.min(76); - self.webview = Some(WebView::new(webview_id, rect)); - } - - compositor.set_painting_order(self.paiting_order()); - self.resize(self.size(), compositor); - - send_to_constellation( - &compositor.constellation_chan, - ConstellationMsg::FocusWebView(webview_id), - ); + /// Check if the window has such webview. + pub fn has_webview(&self, id: WebViewId) -> bool { + self.panel.as_ref().map_or(false, |w| w.webview_id == id) + || self.webview.as_ref().map_or(false, |w| w.webview_id == id) } /// Remove the webview in this window by provided webview ID. If this is the panel, it will @@ -310,29 +332,36 @@ impl Window { &mut self, id: WebViewId, compositor: &mut IOCompositor, - ) -> Option { - if id == self.panel.webview_id { - compositor.maybe_start_shutting_down(); - None + ) -> (Option, bool) { + if self.panel.as_ref().filter(|w| w.webview_id == id).is_some() { + self.webview.as_ref().map(|w| { + send_to_constellation( + &compositor.constellation_chan, + ConstellationMsg::CloseWebView(w.webview_id), + ) + }); + (self.panel.take(), false) } else if self .webview .as_ref() .filter(|w| w.webview_id == id) .is_some() { - self.webview.take() + (self.webview.take(), self.panel.is_none()) } else { - None + (None, false) } } /// Get the painting order of this window. - pub fn paiting_order(&self) -> Vec { + pub fn painting_order(&self) -> Vec { let mut order = vec![]; if let Some(webview) = &self.webview { order.push(webview.clone()); } - order.push(self.panel.clone()); + if let Some(panel) = &self.panel { + order.push(panel.clone()); + } order } @@ -378,3 +407,28 @@ impl Window { self.window.set_cursor_icon(winit_cursor); } } + +/* window decoration */ +#[cfg(macos)] +use cocoa::appkit::{NSWindow, NSWindowStyleMask, NSWindowTitleVisibility}; +#[cfg(macos)] +use objc::runtime::Object; +#[cfg(macos)] +use raw_window_handle::{AppKitWindowHandle, RawWindowHandle}; +#[cfg(macos)] +use winit::dpi::LogicalPosition; + +/// Window decoration for macOS. +#[cfg(macos)] +pub unsafe fn decorate_window(window: *mut Object, _position: LogicalPosition) { + NSWindow::setTitlebarAppearsTransparent_(window, cocoa::base::YES); + NSWindow::setTitleVisibility_(window, NSWindowTitleVisibility::NSWindowTitleHidden); + NSWindow::setStyleMask_( + window, + NSWindowStyleMask::NSTitledWindowMask + | NSWindowStyleMask::NSFullSizeContentViewWindowMask + | NSWindowStyleMask::NSClosableWindowMask + | NSWindowStyleMask::NSResizableWindowMask + | NSWindowStyleMask::NSMiniaturizableWindowMask, + ); +}