From fc7d37e25ea3e93d08161b7ce9182b051d43ef97 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Mon, 27 Nov 2023 23:00:29 +0100 Subject: [PATCH 01/46] Update to winit 0.29 --- Cargo.lock | 699 +++++++++++++----- crates/eframe/Cargo.toml | 6 +- crates/eframe/src/lib.rs | 5 + crates/eframe/src/native/epi_integration.rs | 2 +- crates/eframe/src/native/glow_integration.rs | 26 +- crates/eframe/src/native/run.rs | 273 +++---- crates/eframe/src/native/wgpu_integration.rs | 21 +- crates/eframe/src/native/winit_integration.rs | 4 +- crates/eframe/src/web/app_runner.rs | 16 +- crates/eframe/src/web/events.rs | 21 +- crates/egui-wgpu/Cargo.toml | 2 +- crates/egui-winit/Cargo.toml | 4 +- crates/egui-winit/src/lib.rs | 316 ++++---- crates/egui/src/viewport.rs | 2 +- crates/egui_demo_app/Cargo.toml | 2 +- crates/egui_glow/Cargo.toml | 4 +- crates/egui_glow/examples/pure_glow.rs | 55 +- crates/egui_glow/src/winit.rs | 2 +- 18 files changed, 913 insertions(+), 547 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41061aac7cf..fcbe104c417 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,9 +20,9 @@ checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" [[package]] name = "accesskit" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0cc53b7e5d8f45ebe687178cf91af0f45fdba6e78fedf94f0269c5be5b9f296" +checksum = "ca8410747ed85a17c4a1e9ed3f5a74d3e7bdcc876cf9a18ff40ae21d645997b2" dependencies = [ "enumn", "serde", @@ -30,30 +30,30 @@ dependencies = [ [[package]] name = "accesskit_consumer" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39dfcfd32eb0c1b525daaf4b02adcd2fa529c22cd713491e15bf002a01a714f5" +checksum = "8c17cca53c09fbd7288667b22a201274b9becaa27f0b91bf52a526db95de45e6" dependencies = [ "accesskit", ] [[package]] name = "accesskit_macos" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c7e8406319ac3149d7b59983637984f0864bbf738319b1c443976268b6426c" +checksum = "cd3b6ae1eabbfbced10e840fd3fce8a93ae84f174b3e4ba892ab7bcb42e477a7" dependencies = [ "accesskit", "accesskit_consumer", - "objc2", + "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", ] [[package]] name = "accesskit_unix" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0c84552a7995c981d5f22e2d4b24ba9a55718bb12fba883506d6d7344acaf1" +checksum = "6c8c9b4467d77cacfbc93cee9aa8e7822f6d527c774efdca5f8b3a5280c34847" dependencies = [ "accesskit", "accesskit_consumer", @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "accesskit_windows" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "314d4a797fc82d182b04f4f0665a368924fb556ad9557fccd2d39d38dc8c1c1b" +checksum = "afcae27ec0974fc7c3b0b318783be89fd1b2e66dd702179fe600166a38ff4a0b" dependencies = [ "accesskit", "accesskit_consumer", @@ -82,9 +82,9 @@ dependencies = [ [[package]] name = "accesskit_winit" -version = "0.15.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88e39fcec2e10971e188730b7a76bab60647dacc973d4591855ebebcadfaa738" +checksum = "5284218aca17d9e150164428a0ebc7b955f70e3a9a78b4c20894513aabf98a67" dependencies = [ "accesskit", "accesskit_macos", @@ -115,6 +115,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", + "getrandom", "once_cell", "serde", "version_check", @@ -138,20 +139,23 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "android-activity" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c77a0045eda8b888c76ea473c2b0515ba6f471d318f8927c5c72240937035a6" +checksum = "052ad56e336bcc615a214bffbeca6c181ee9550acec193f0327e0b103b033a4d" dependencies = [ "android-properties", - "bitflags 1.3.2", + "bitflags 2.4.0", "cc", + "cesu8", + "jni", "jni-sys", "libc", "log", - "ndk", + "ndk 0.8.0", "ndk-context", - "ndk-sys", - "num_enum", + "ndk-sys 0.5.0+25.2.9519653", + "num_enum 0.7.1", + "thiserror", ] [[package]] @@ -201,7 +205,7 @@ dependencies = [ "parking_lot", "thiserror", "winapi", - "x11rb", + "x11rb 0.10.1", ] [[package]] @@ -216,6 +220,12 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5f312b0a56c5cdf967c0aeb67f6289603354951683bc97ddc595ab974ba9aa" + [[package]] name = "ash" version = "0.37.3+1.3.251" @@ -285,7 +295,7 @@ dependencies = [ "futures-lite", "log", "parking", - "polling", + "polling 2.8.0", "rustix 0.37.25", "slab", "socket2", @@ -320,7 +330,7 @@ dependencies = [ "cfg-if", "event-listener 3.0.0", "futures-lite", - "rustix 0.38.14", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -564,7 +574,16 @@ version = "0.1.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" dependencies = [ - "objc-sys", + "objc-sys 0.2.0-beta.2", +] + +[[package]] +name = "block-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dd7cf50912cddc06dc5ea7c08c5e81c1b2c842a70d19def1848d54c586fed92" +dependencies = [ + "objc-sys 0.3.1", ] [[package]] @@ -573,8 +592,18 @@ version = "0.2.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" dependencies = [ - "block-sys", - "objc2-encode", + "block-sys 0.1.0-beta.1", + "objc2-encode 2.0.0-pre.2", +] + +[[package]] +name = "block2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" +dependencies = [ + "block-sys 0.2.0", + "objc2 0.4.1", ] [[package]] @@ -643,16 +672,28 @@ dependencies = [ [[package]] name = "calloop" -version = "0.10.6" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e0d00eb1ea24371a97d2da6201c6747a633dc6dc1988ef503403b4c59504a8" +checksum = "7b50b5a44d59a98c55a9eeb518f39bf7499ba19fd98ee7d22618687f3f10adbf" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "log", - "nix 0.25.1", - "slotmap", + "polling 3.3.0", + "rustix 0.38.21", + "slab", "thiserror", - "vec_map", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" +dependencies = [ + "calloop", + "rustix 0.38.21", + "wayland-backend", + "wayland-client 0.31.1", ] [[package]] @@ -817,7 +858,7 @@ dependencies = [ "block", "cocoa-foundation", "core-foundation", - "core-graphics", + "core-graphics 0.22.3", "foreign-types 0.3.2", "libc", "objc", @@ -921,6 +962,19 @@ dependencies = [ "libc", ] +[[package]] +name = "core-graphics" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", +] + [[package]] name = "core-graphics-types" version = "0.1.2" @@ -1013,6 +1067,12 @@ dependencies = [ "typenum", ] +[[package]] +name = "cursor-icon" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" + [[package]] name = "custom_3d_glow" version = "0.1.0" @@ -1238,7 +1298,7 @@ dependencies = [ "percent-encoding", "pollster", "puffin", - "raw-window-handle", + "raw-window-handle 0.5.2", "ron", "serde", "static_assertions", @@ -1294,7 +1354,7 @@ dependencies = [ "egui", "log", "puffin", - "raw-window-handle", + "raw-window-handle 0.5.2", "serde", "smithay-clipboard", "web-time", @@ -1357,7 +1417,7 @@ dependencies = [ "resvg", "serde", "syntect", - "tiny-skia", + "tiny-skia 0.8.4", "usvg", ] @@ -1375,7 +1435,7 @@ dependencies = [ "log", "memoffset 0.7.1", "puffin", - "raw-window-handle", + "raw-window-handle 0.5.2", "wasm-bindgen", "web-sys", ] @@ -1790,6 +1850,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "gethostname" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -1875,68 +1945,60 @@ dependencies = [ [[package]] name = "glutin" -version = "0.30.10" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc93b03242719b8ad39fb26ed2b01737144ce7bd4bfc7adadcef806596760fe" +checksum = "eca18d477e18c996c1fd1a50e04c6a745b67e2d512c7fb51f2757d9486a0e3ee" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "cfg_aliases", "cgl", "core-foundation", "dispatch", "glutin_egl_sys", "glutin_glx_sys", - "glutin_wgl_sys 0.4.0", - "libloading 0.7.4", - "objc2", + "glutin_wgl_sys", + "icrate", + "libloading 0.8.0", + "objc2 0.4.1", "once_cell", - "raw-window-handle", - "wayland-sys 0.30.1", - "windows-sys 0.45.0", + "raw-window-handle 0.5.2", + "wayland-sys 0.31.1", + "windows-sys 0.48.0", "x11-dl", ] [[package]] name = "glutin-winit" -version = "0.3.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629a873fc04062830bfe8f97c03773bcd7b371e23bcc465d0a61448cd1588fa4" +checksum = "1ebcdfba24f73b8412c5181e56f092b5eff16671c514ce896b258a0a64bd7735" dependencies = [ "cfg_aliases", "glutin", - "raw-window-handle", + "raw-window-handle 0.5.2", "winit", ] [[package]] name = "glutin_egl_sys" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af784eb26c5a68ec85391268e074f0aa618c096eadb5d6330b0911cf34fe57c5" +checksum = "77cc5623f5309ef433c3dd4ca1223195347fe62c413da8e2fdd0eb76db2d9bcd" dependencies = [ "gl_generator", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "glutin_glx_sys" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b53cb5fe568964aa066a3ba91eac5ecbac869fb0842cd0dc9e412434f1a1494" +checksum = "a165fd686c10dcc2d45380b35796e577eacfd43d4660ee741ec8ebe2201b3b4f" dependencies = [ "gl_generator", "x11-dl", ] -[[package]] -name = "glutin_wgl_sys" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef89398e90033fc6bc65e9bd42fd29bbbfd483bda5b56dc5562f455550618165" -dependencies = [ - "gl_generator", -] - [[package]] name = "glutin_wgl_sys" version = "0.5.0" @@ -2161,6 +2223,17 @@ dependencies = [ "cc", ] +[[package]] +name = "icrate" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" +dependencies = [ + "block2 0.3.0", + "dispatch", + "objc2 0.4.1", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2235,9 +2308,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", ] [[package]] @@ -2258,7 +2328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.3", - "rustix 0.38.14", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -2418,9 +2488,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.7" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "litrs" @@ -2474,6 +2544,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deaba38d7abf1d4cca21cc89e932e542ba2b9258664d2a9ef0e61512039c9375" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -2545,18 +2624,6 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - [[package]] name = "multiple_viewports" version = "0.1.0" @@ -2602,9 +2669,25 @@ checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" dependencies = [ "bitflags 1.3.2", "jni-sys", - "ndk-sys", - "num_enum", - "raw-window-handle", + "ndk-sys 0.4.1+23.1.7779620", + "num_enum 0.5.11", + "raw-window-handle 0.5.2", + "thiserror", +] + +[[package]] +name = "ndk" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +dependencies = [ + "bitflags 2.4.0", + "jni-sys", + "log", + "ndk-sys 0.5.0+25.2.9519653", + "num_enum 0.7.1", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.0", "thiserror", ] @@ -2622,10 +2705,10 @@ checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f" dependencies = [ "libc", "log", - "ndk", + "ndk 0.7.0", "ndk-context", "ndk-macro", - "ndk-sys", + "ndk-sys 0.4.1+23.1.7779620", "once_cell", "parking_lot", ] @@ -2653,24 +2736,20 @@ dependencies = [ ] [[package]] -name = "nix" -version = "0.24.3" +name = "ndk-sys" +version = "0.5.0+25.2.9519653" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.6.5", + "jni-sys", ] [[package]] name = "nix" -version = "0.25.1" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "autocfg", "bitflags 1.3.2", "cfg-if", "libc", @@ -2741,7 +2820,16 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +dependencies = [ + "num_enum_derive 0.7.1", ] [[package]] @@ -2756,6 +2844,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num_enum_derive" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.37", +] + [[package]] name = "objc" version = "0.2.7" @@ -2783,15 +2883,31 @@ version = "0.2.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" +[[package]] +name = "objc-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99e1d07c6eab1ce8b6382b8e3c7246fe117ff3f8b34be065f5ebace6749fe845" + [[package]] name = "objc2" version = "0.3.0-beta.3.patch-leaks.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" dependencies = [ - "block2", - "objc-sys", - "objc2-encode", + "block2 0.2.0-alpha.6", + "objc-sys 0.2.0-beta.2", + "objc2-encode 2.0.0-pre.2", +] + +[[package]] +name = "objc2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" +dependencies = [ + "objc-sys 0.3.1", + "objc2-encode 3.0.0", ] [[package]] @@ -2800,9 +2916,15 @@ version = "2.0.0-pre.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" dependencies = [ - "objc-sys", + "objc-sys 0.2.0-beta.2", ] +[[package]] +name = "objc2-encode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" + [[package]] name = "objc_exception" version = "0.1.2" @@ -2985,7 +3107,7 @@ dependencies = [ "base64 0.21.4", "indexmap 1.9.3", "line-wrap", - "quick-xml", + "quick-xml 0.29.0", "serde", "time", ] @@ -3029,6 +3151,20 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "polling" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53b6af1f60f36f8c2ac2aad5459d75a5a9b4be1e8cdd40264f315d78193e531" +dependencies = [ + "cfg-if", + "concurrent-queue", + "pin-project-lite", + "rustix 0.38.21", + "tracing", + "windows-sys 0.48.0", +] + [[package]] name = "pollster" version = "0.3.0" @@ -3129,6 +3265,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick-xml" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.33" @@ -3180,6 +3325,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +[[package]] +name = "raw-window-handle" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544" + [[package]] name = "rctree" version = "0.5.0" @@ -3260,7 +3411,7 @@ dependencies = [ "pico-args", "rgb", "svgtypes", - "tiny-skia", + "tiny-skia 0.8.4", "usvg", ] @@ -3282,7 +3433,7 @@ dependencies = [ "objc", "objc-foundation", "objc_id", - "raw-window-handle", + "raw-window-handle 0.5.2", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -3362,14 +3513,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.14" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ "bitflags 2.4.0", "errno", "libc", - "linux-raw-sys 0.4.7", + "linux-raw-sys 0.4.11", "windows-sys 0.48.0", ] @@ -3460,15 +3611,15 @@ dependencies = [ [[package]] name = "sctk-adwaita" -version = "0.5.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda4e97be1fd174ccc2aae81c8b694e803fa99b34e8fd0f057a9d70698e3ed09" +checksum = "1729a30a469de249c6effc17ec8d039b0aa29b3af79b819b7f51cb6ab8046a90" dependencies = [ "ab_glyph", "log", - "memmap2", - "smithay-client-toolkit", - "tiny-skia", + "memmap2 0.9.0", + "smithay-client-toolkit 0.18.0", + "tiny-skia 0.11.2", ] [[package]] @@ -3608,16 +3759,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "870427e30b8f2cbe64bf43ec4b86e88fe39b0a84b3f15efd9c9c2d020bc86eb9" dependencies = [ "bitflags 1.3.2", - "calloop", "dlib", "lazy_static", "log", - "memmap2", + "memmap2 0.5.10", "nix 0.24.3", "pkg-config", - "wayland-client", - "wayland-cursor", - "wayland-protocols", + "wayland-client 0.29.5", + "wayland-cursor 0.29.5", + "wayland-protocols 0.29.5", +] + +[[package]] +name = "smithay-client-toolkit" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e3d9941fa3bacf7c2bf4b065304faa14164151254cd16ce1b1bc8fc381600f" +dependencies = [ + "bitflags 2.4.0", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2 0.9.0", + "rustix 0.38.21", + "thiserror", + "wayland-backend", + "wayland-client 0.31.1", + "wayland-csd-frame", + "wayland-cursor 0.31.0", + "wayland-protocols 0.31.0", + "wayland-protocols-wlr", + "wayland-scanner 0.31.0", + "xkeysym", ] [[package]] @@ -3626,8 +3801,17 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8" dependencies = [ - "smithay-client-toolkit", - "wayland-client", + "smithay-client-toolkit 0.16.1", + "wayland-client 0.29.5", +] + +[[package]] +name = "smol_str" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +dependencies = [ + "serde", ] [[package]] @@ -3792,7 +3976,7 @@ dependencies = [ "cfg-if", "fastrand 2.0.1", "redox_syscall 0.3.5", - "rustix 0.38.14", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -3878,7 +4062,21 @@ dependencies = [ "bytemuck", "cfg-if", "png", - "tiny-skia-path", + "tiny-skia-path 0.8.4", +] + +[[package]] +name = "tiny-skia" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b72a92a05db376db09fe6d50b7948d106011761c05a6a45e23e17ee9b556222" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path 0.11.2", ] [[package]] @@ -3892,6 +4090,17 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tiny-skia-path" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac3865b9708fc7e1961a65c3a4fa55e984272f33092d3c859929f887fceb647" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -4068,6 +4277,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.11" @@ -4147,12 +4362,6 @@ dependencies = [ "svgtypes", ] -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version-compare" version = "0.1.1" @@ -4189,9 +4398,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4199,9 +4408,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", @@ -4226,9 +4435,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4236,9 +4445,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", @@ -4249,9 +4458,23 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" + +[[package]] +name = "wayland-backend" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19152ddd73f45f024ed4534d9ca2594e0ef252c1847695255dae47f34df9fbe4" +dependencies = [ + "cc", + "downcast-rs", + "nix 0.26.4", + "scoped-tls", + "smallvec", + "wayland-sys 0.31.1", +] [[package]] name = "wayland-client" @@ -4265,10 +4488,22 @@ dependencies = [ "nix 0.24.3", "scoped-tls", "wayland-commons", - "wayland-scanner", + "wayland-scanner 0.29.5", "wayland-sys 0.29.5", ] +[[package]] +name = "wayland-client" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ca7d52347346f5473bf2f56705f360e8440873052e575e55890c4fa57843ed3" +dependencies = [ + "bitflags 2.4.0", + "nix 0.26.4", + "wayland-backend", + "wayland-scanner 0.31.0", +] + [[package]] name = "wayland-commons" version = "0.29.5" @@ -4281,6 +4516,17 @@ dependencies = [ "wayland-sys 0.29.5", ] +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.4.0", + "cursor-icon", + "wayland-backend", +] + [[package]] name = "wayland-cursor" version = "0.29.5" @@ -4288,7 +4534,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" dependencies = [ "nix 0.24.3", - "wayland-client", + "wayland-client 0.29.5", + "xcursor", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44aa20ae986659d6c77d64d808a046996a932aa763913864dc40c359ef7ad5b" +dependencies = [ + "nix 0.26.4", + "wayland-client 0.31.1", "xcursor", ] @@ -4299,9 +4556,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" dependencies = [ "bitflags 1.3.2", - "wayland-client", + "wayland-client 0.29.5", "wayland-commons", - "wayland-scanner", + "wayland-scanner 0.29.5", +] + +[[package]] +name = "wayland-protocols" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e253d7107ba913923dc253967f35e8561a3c65f914543e46843c88ddd729e21c" +dependencies = [ + "bitflags 2.4.0", + "wayland-backend", + "wayland-client 0.31.1", + "wayland-scanner 0.31.0", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +dependencies = [ + "bitflags 2.4.0", + "wayland-backend", + "wayland-client 0.31.1", + "wayland-protocols 0.31.0", + "wayland-scanner 0.31.0", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +dependencies = [ + "bitflags 2.4.0", + "wayland-backend", + "wayland-client 0.31.1", + "wayland-protocols 0.31.0", + "wayland-scanner 0.31.0", ] [[package]] @@ -4315,6 +4610,17 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "wayland-scanner" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb8e28403665c9f9513202b7e1ed71ec56fde5c107816843fb14057910b2c09c" +dependencies = [ + "proc-macro2", + "quick-xml 0.30.0", + "quote", +] + [[package]] name = "wayland-sys" version = "0.29.5" @@ -4328,13 +4634,13 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.30.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b2a02ac608e07132978689a6f9bf4214949c85998c247abadd4f4129b1aa06" +checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" dependencies = [ "dlib", - "lazy_static", "log", + "once_cell", "pkg-config", ] @@ -4371,7 +4677,7 @@ dependencies = [ "log", "ndk-context", "objc", - "raw-window-handle", + "raw-window-handle 0.5.2", "url", "web-sys", ] @@ -4396,7 +4702,7 @@ dependencies = [ "naga", "parking_lot", "profiling", - "raw-window-handle", + "raw-window-handle 0.5.2", "smallvec", "static_assertions", "wasm-bindgen", @@ -4421,7 +4727,7 @@ dependencies = [ "naga", "parking_lot", "profiling", - "raw-window-handle", + "raw-window-handle 0.5.2", "rustc-hash", "smallvec", "thiserror", @@ -4445,7 +4751,7 @@ dependencies = [ "core-graphics-types", "d3d12", "glow 0.13.0", - "glutin_wgl_sys 0.5.0", + "glutin_wgl_sys", "gpu-alloc", "gpu-allocator", "gpu-descriptor", @@ -4462,7 +4768,7 @@ dependencies = [ "parking_lot", "profiling", "range-alloc", - "raw-window-handle", + "raw-window-handle 0.5.2", "renderdoc-sys", "rustc-hash", "smallvec", @@ -4493,7 +4799,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.14", + "rustix 0.38.21", ] [[package]] @@ -4737,37 +5043,51 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winit" -version = "0.28.7" +version = "0.29.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9596d90b45384f5281384ab204224876e8e8bf7d58366d9b795ad99aa9894b94" +checksum = "d25d662bb83b511acd839534bb2d88521b0bbc81440969cb077d23c4db9e62c7" dependencies = [ + "ahash", "android-activity", - "bitflags 1.3.2", + "atomic-waker", + "bitflags 2.4.0", + "bytemuck", + "calloop", "cfg_aliases", "core-foundation", - "core-graphics", - "dispatch", - "instant", + "core-graphics 0.23.1", + "cursor-icon", + "icrate", + "js-sys", "libc", "log", - "mio", - "ndk", - "objc2", + "memmap2 0.9.0", + "ndk 0.8.0", + "ndk-sys 0.5.0+25.2.9519653", + "objc2 0.4.1", "once_cell", "orbclient", "percent-encoding", - "raw-window-handle", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.0", "redox_syscall 0.3.5", + "rustix 0.38.21", "sctk-adwaita", - "smithay-client-toolkit", + "smithay-client-toolkit 0.18.0", + "smol_str", + "unicode-segmentation", "wasm-bindgen", - "wayland-client", - "wayland-commons", - "wayland-protocols", - "wayland-scanner", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client 0.31.1", + "wayland-protocols 0.31.0", + "wayland-protocols-plasma", "web-sys", - "windows-sys 0.45.0", + "web-time", + "windows-sys 0.48.0", "x11-dl", + "x11rb 0.12.0", + "xkbcommon-dl", ] [[package]] @@ -4796,11 +5116,28 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" dependencies = [ - "gethostname", + "gethostname 0.2.3", "nix 0.24.3", "winapi", "winapi-wsapoll", - "x11rb-protocol", + "x11rb-protocol 0.10.0", +] + +[[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 0.3.0", + "libc", + "libloading 0.7.4", + "nix 0.26.4", + "once_cell", + "winapi", + "winapi-wsapoll", + "x11rb-protocol 0.12.0", ] [[package]] @@ -4812,6 +5149,15 @@ dependencies = [ "nix 0.24.3", ] +[[package]] +name = "x11rb-protocol" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" +dependencies = [ + "nix 0.26.4", +] + [[package]] name = "xcursor" version = "0.3.4" @@ -4831,6 +5177,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "xkbcommon-dl" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6924668544c48c0133152e7eec86d644a056ca3d09275eb8d5cdb9855f9d8699" +dependencies = [ + "bitflags 2.4.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054a8e68b76250b253f671d1268cb7f1ae089ec35e195b2efb2a4e9a836d0621" + [[package]] name = "xml-rs" version = "0.8.19" diff --git a/crates/eframe/Cargo.toml b/crates/eframe/Cargo.toml index df4fe36e356..0178b0964b9 100644 --- a/crates/eframe/Cargo.toml +++ b/crates/eframe/Cargo.toml @@ -127,7 +127,7 @@ image = { version = "0.24", default-features = false, features = [ "png", ] } # Needed for app icon raw-window-handle.workspace = true -winit = { version = "0.28.1", default-features = false } +winit = { version = "0.29", default-features = false, features = ["rwh_05"] } # optional native: directories-next = { version = "2", optional = true } @@ -138,8 +138,8 @@ pollster = { version = "0.3", optional = true } # needed for wgpu # we can expose these to user so that they can select which backends they want to enable to avoid compiling useless deps. # this can be done at the same time we expose x11/wayland features of winit crate. -glutin = { version = "0.30", optional = true } -glutin-winit = { version = "0.3.0", optional = true } +glutin = { version = "0.31", optional = true } +glutin-winit = { version = "0.4", optional = true } puffin = { workspace = true, optional = true } wgpu = { workspace = true, optional = true } diff --git a/crates/eframe/src/lib.rs b/crates/eframe/src/lib.rs index 5f47335b3a1..ff30cf283e3 100644 --- a/crates/eframe/src/lib.rs +++ b/crates/eframe/src/lib.rs @@ -316,6 +316,11 @@ pub enum Error { #[error("winit error: {0}")] Winit(#[from] winit::error::OsError), + /// An error from [`winit::EventLoop`]. + #[cfg(not(target_arch = "wasm32"))] + #[error("winit EventLoopError: {0}")] + WinitEventLoop(#[from] winit::error::EventLoopError), + /// An error from [`glutin`] when using [`glow`]. #[cfg(all(feature = "glow", not(target_arch = "wasm32")))] #[error("glutin error: {0}")] diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index 40e756c0846..eb42a5a6145 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -229,7 +229,7 @@ impl EpiIntegration { pub fn on_window_event( &mut self, - event: &winit::event::WindowEvent<'_>, + event: &winit::event::WindowEvent, egui_winit: &mut egui_winit::State, ) -> EventResponse { crate::profile_function!(egui_winit::short_window_event_description(event)); diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index 9a820bec770..0041a2d7593 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -1,8 +1,9 @@ use std::{cell::RefCell, rc::Rc, sync::Arc, time::Instant}; use glutin::{ + context::NotCurrentGlContext, display::GetGlDisplay, - prelude::{GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext}, + prelude::{GlDisplay, PossiblyCurrentGlContext}, surface::GlSurface, }; use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _}; @@ -154,8 +155,7 @@ impl GlowWinitApp { event_loop, native_options, window_settings, - ) - .with_visible(false); // Start hidden until we render the first frame to fix white flash on startup (https://github.com/emilk/egui/pull/3631) + ); let mut glutin_window_context = unsafe { GlutinWindowContext::new(egui_ctx, winit_window_builder, native_options, event_loop)? @@ -403,7 +403,7 @@ impl WinitApp for GlowWinitApp { fn on_event( &mut self, event_loop: &EventLoopWindowTarget, - event: &winit::event::Event<'_, UserEvent>, + event: &winit::event::Event, ) -> Result { crate::profile_function!(winit_integration::short_event_description(event)); @@ -435,15 +435,6 @@ impl WinitApp for GlowWinitApp { EventResult::Wait } - winit::event::Event::MainEventsCleared => { - if let Some(running) = &self.running { - if let Err(err) = running.glutin.borrow_mut().on_resume(event_loop) { - log::warn!("on_resume failed {err}"); - } - } - EventResult::Wait - } - winit::event::Event::WindowEvent { event, window_id } => { if let Some(running) = &mut self.running { running.on_window_event(*window_id, event) @@ -665,7 +656,7 @@ impl GlowWinitRunning { fn on_window_event( &mut self, window_id: WindowId, - event: &winit::event::WindowEvent<'_>, + event: &winit::event::WindowEvent, ) -> EventResult { crate::profile_function!(egui_winit::short_window_event_description(event)); @@ -704,10 +695,9 @@ impl GlowWinitRunning { } } - winit::event::WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - if let Some(viewport_id) = viewport_id { + winit::event::WindowEvent::ScaleFactorChanged { .. } => { + if viewport_id.is_some() { repaint_asap = true; - glutin.resize(viewport_id, **new_inner_size); } } @@ -822,7 +812,7 @@ impl GlutinWindowContext { // Create GL display. This may probably create a window too on most platforms. Definitely on `MS windows`. Never on Android. let display_builder = glutin_winit::DisplayBuilder::new() // we might want to expose this option to users in the future. maybe using an env var or using native_options. - .with_preference(glutin_winit::ApiPrefence::FallbackEgl) // https://github.com/emilk/egui/issues/2520#issuecomment-1367841150 + .with_preference(glutin_winit::ApiPreference::FallbackEgl) // https://github.com/emilk/egui/issues/2520#issuecomment-1367841150 .with_window_builder(Some(create_winit_window_builder( egui_ctx, event_loop, diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 5e3dc91554c..82ed5c6473e 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -39,7 +39,7 @@ fn create_event_loop(native_options: &mut epi::NativeOptions) -> EventLoop, mut winit_app: impl WinitApp, ) -> Result<()> { - use winit::{event_loop::ControlFlow, platform::run_return::EventLoopExtRunReturn as _}; + use winit::{event_loop::ControlFlow, platform::run_on_demand::EventLoopExtRunOnDemand}; log::debug!("Entering the winit event loop (run_return)…"); @@ -76,20 +76,22 @@ fn run_and_return( let mut returned_result = Ok(()); - event_loop.run_return(|event, event_loop, control_flow| { + event_loop.run_on_demand(|event, event_loop_window_target| { crate::profile_scope!("winit_event", short_event_description(&event)); let event_result = match &event { - winit::event::Event::LoopDestroyed => { - // On Mac, Cmd-Q we get here and then `run_return` doesn't return (despite its name), + winit::event::Event::LoopExiting => { + // On Mac, Cmd-Q we get here and then `run_on_demand` doesn't return (despite its name), // so we need to save state now: - log::debug!("Received Event::LoopDestroyed - saving app state…"); + log::debug!("Received Event::LoopExiting - saving app state…"); winit_app.save_and_destroy(); - *control_flow = ControlFlow::Exit; return; } - winit::event::Event::RedrawRequested(window_id) => { + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + window_id, + } => { windows_next_repaint_times.remove(window_id); winit_app.run_ui_and_paint(*window_id) } @@ -120,7 +122,7 @@ fn run_and_return( EventResult::Wait } - event => match winit_app.on_event(event_loop, event) { + event => match winit_app.on_event(event_loop_window_target, event) { Ok(event_result) => event_result, Err(err) => { log::error!("Exiting because of error: {err} during event {event:?}"); @@ -132,7 +134,7 @@ fn run_and_return( match event_result { EventResult::Wait => { - control_flow.set_wait(); + event_loop_window_target.set_control_flow(ControlFlow::Wait); } EventResult::RepaintNow(window_id) => { log::trace!("Repaint caused by {}", short_event_description(&event)); @@ -160,7 +162,7 @@ fn run_and_return( EventResult::Exit => { log::debug!("Asking to exit event loop…"); winit_app.save_and_destroy(); - *control_flow = ControlFlow::Exit; + event_loop_window_target.exit(); return; } } @@ -171,7 +173,10 @@ fn run_and_return( use winit::event::Event; if matches!( event, - Event::RedrawEventsCleared | Event::RedrawRequested(_) | Event::Resumed + Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + .. + } | Event::Resumed ) { windows_next_repaint_times.retain(|window_id, repaint_time| { if Instant::now() < *repaint_time { @@ -179,7 +184,7 @@ fn run_and_return( }; next_repaint_time = None; - control_flow.set_poll(); + event_loop_window_target.set_control_flow(ControlFlow::Poll); if let Some(window) = winit_app.window(*window_id) { log::trace!("request_redraw for {window_id:?}"); @@ -196,9 +201,9 @@ fn run_and_return( if time_until_next < std::time::Duration::from_secs(10_000) { log::trace!("WaitUntil {time_until_next:?}"); } - control_flow.set_wait_until(next_repaint_time); + event_loop_window_target.set_control_flow(ControlFlow::WaitUntil(next_repaint_time)); }; - }); + })?; log::debug!("eframe window closed"); @@ -219,140 +224,154 @@ fn run_and_return( returned_result } -fn run_and_exit(event_loop: EventLoop, mut winit_app: impl WinitApp + 'static) -> ! { +fn run_and_exit( + event_loop: EventLoop, + mut winit_app: impl WinitApp + 'static, +) -> Result<()> { + use winit::event_loop::ControlFlow; log::debug!("Entering the winit event loop (run)…"); // When to repaint what window let mut windows_next_repaint_times = HashMap::default(); - event_loop.run(move |event, event_loop, control_flow| { - crate::profile_scope!("winit_event", short_event_description(&event)); + event_loop + .run(move |event, event_loop_window_target| { + crate::profile_scope!("winit_event", short_event_description(&event)); - let event_result = match &event { - winit::event::Event::LoopDestroyed => { - log::debug!("Received Event::LoopDestroyed"); - EventResult::Exit - } + let event_result = match &event { + winit::event::Event::LoopExiting => { + log::debug!("Received Event::LoopExiting"); + EventResult::Exit + } - winit::event::Event::RedrawRequested(window_id) => { - windows_next_repaint_times.remove(window_id); - winit_app.run_ui_and_paint(*window_id) - } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + window_id, + } => { + windows_next_repaint_times.remove(window_id); + winit_app.run_ui_and_paint(*window_id) + } - winit::event::Event::UserEvent(UserEvent::RequestRepaint { - when, - frame_nr, - viewport_id, - }) => { - let current_frame_nr = winit_app.frame_nr(*viewport_id); - if current_frame_nr == *frame_nr || current_frame_nr == *frame_nr + 1 { - if let Some(window_id) = winit_app.window_id_from_viewport_id(*viewport_id) { - EventResult::RepaintAt(window_id, *when) + winit::event::Event::UserEvent(UserEvent::RequestRepaint { + when, + frame_nr, + viewport_id, + }) => { + let current_frame_nr = winit_app.frame_nr(*viewport_id); + if current_frame_nr == *frame_nr || current_frame_nr == *frame_nr + 1 { + if let Some(window_id) = winit_app.window_id_from_viewport_id(*viewport_id) + { + EventResult::RepaintAt(window_id, *when) + } else { + EventResult::Wait + } } else { - EventResult::Wait + log::trace!("Got outdated UserEvent::RequestRepaint"); + EventResult::Wait // old request - we've already repainted } - } else { - log::trace!("Got outdated UserEvent::RequestRepaint"); - EventResult::Wait // old request - we've already repainted } - } - winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached { - .. - }) => { - log::trace!("Woke up to check next_repaint_time"); - EventResult::Wait - } - - event => match winit_app.on_event(event_loop, event) { - Ok(event_result) => event_result, - Err(err) => { - panic!("eframe encountered a fatal error: {err} during event {event:?}"); + winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached { + .. + }) => { + log::trace!("Woke up to check next_repaint_time"); + EventResult::Wait } - }, - }; - match event_result { - EventResult::Wait => { - control_flow.set_wait(); - } - EventResult::RepaintNow(window_id) => { - log::trace!("Repaint caused by {}", short_event_description(&event)); - if cfg!(target_os = "windows") { - // Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 - windows_next_repaint_times.remove(&window_id); + event => match winit_app.on_event(event_loop_window_target, event) { + Ok(event_result) => event_result, + Err(err) => { + panic!("eframe encountered a fatal error: {err} during event {event:?}"); + } + }, + }; - winit_app.run_ui_and_paint(window_id); - } else { - // Fix for https://github.com/emilk/egui/issues/2425 - windows_next_repaint_times.insert(window_id, Instant::now()); + match event_result { + EventResult::Wait => { + event_loop_window_target.set_control_flow(ControlFlow::Wait); } - } - EventResult::RepaintNext(window_id) => { - log::trace!("Repaint caused by {}", short_event_description(&event)); - windows_next_repaint_times.insert(window_id, Instant::now()); - } - EventResult::RepaintAt(window_id, repaint_time) => { - windows_next_repaint_times.insert( - window_id, - windows_next_repaint_times - .get(&window_id) - .map_or(repaint_time, |last| (*last).min(repaint_time)), - ); - } - EventResult::Exit => { - log::debug!("Quitting - saving app state…"); - winit_app.save_and_destroy(); - #[allow(clippy::exit)] - std::process::exit(0); - } - } + EventResult::RepaintNow(window_id) => { + log::trace!("Repaint caused by {}", short_event_description(&event)); + if cfg!(target_os = "windows") { + // Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 + windows_next_repaint_times.remove(&window_id); - let mut next_repaint_time = windows_next_repaint_times.values().min().copied(); - - // This is for not duplicating redraw requests - use winit::event::Event; - if matches!( - event, - Event::RedrawEventsCleared | Event::RedrawRequested(_) | Event::Resumed - ) { - windows_next_repaint_times.retain(|window_id, repaint_time| { - if Instant::now() < *repaint_time { - return true; + winit_app.run_ui_and_paint(window_id); + } else { + // Fix for https://github.com/emilk/egui/issues/2425 + windows_next_repaint_times.insert(window_id, Instant::now()); + } } + EventResult::RepaintNext(window_id) => { + log::trace!("Repaint caused by {}", short_event_description(&event)); + windows_next_repaint_times.insert(window_id, Instant::now()); + } + EventResult::RepaintAt(window_id, repaint_time) => { + windows_next_repaint_times.insert( + window_id, + windows_next_repaint_times + .get(&window_id) + .map_or(repaint_time, |last| (*last).min(repaint_time)), + ); + } + EventResult::Exit => { + log::debug!("Quitting - saving app state…"); + winit_app.save_and_destroy(); + #[allow(clippy::exit)] + std::process::exit(0); + } + } - next_repaint_time = None; - control_flow.set_poll(); + let mut next_repaint_time = windows_next_repaint_times.values().min().copied(); + + // This is for not duplicating redraw requests + use winit::event::Event; + if matches!( + event, + Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + .. + } | Event::Resumed + ) { + windows_next_repaint_times.retain(|window_id, repaint_time| { + if Instant::now() < *repaint_time { + return true; + } - if let Some(window) = winit_app.window(*window_id) { - log::trace!("request_redraw for {window_id:?}"); - window.request_redraw(); - true - } else { - false - } - }); - } + next_repaint_time = None; + event_loop_window_target.set_control_flow(ControlFlow::Poll); - if let Some(next_repaint_time) = next_repaint_time { - let time_until_next = next_repaint_time.saturating_duration_since(Instant::now()); - if time_until_next < std::time::Duration::from_secs(10_000) { - log::trace!("WaitUntil {time_until_next:?}"); + if let Some(window) = winit_app.window(*window_id) { + log::trace!("request_redraw for {window_id:?}"); + window.request_redraw(); + true + } else { + false + } + }); } - // WaitUntil seems to not work on iOS - #[cfg(target_os = "ios")] - winit_app - .get_window_winit_id(ViewportId::ROOT) - .map(|window_id| { - winit_app - .window(window_id) - .map(|window| window.request_redraw()) - }); + if let Some(next_repaint_time) = next_repaint_time { + let time_until_next = next_repaint_time.saturating_duration_since(Instant::now()); + if time_until_next < std::time::Duration::from_secs(10_000) { + log::trace!("WaitUntil {time_until_next:?}"); + } - control_flow.set_wait_until(next_repaint_time); - }; - }) + // WaitUntil seems to not work on iOS + #[cfg(target_os = "ios")] + winit_app + .get_window_winit_id(ViewportId::ROOT) + .map(|window_id| { + winit_app + .window(window_id) + .map(|window| window.request_redraw()) + }); + + event_loop_window_target + .set_control_flow(ControlFlow::WaitUntil(next_repaint_time)); + }; + }) + .map_err(|e| e.into()) } // ---------------------------------------------------------------------------- @@ -375,7 +394,7 @@ pub fn run_glow( let event_loop = create_event_loop(&mut native_options); let glow_eframe = GlowWinitApp::new(&event_loop, app_name, native_options, app_creator); - run_and_exit(event_loop, glow_eframe); + run_and_exit(event_loop, glow_eframe) } // ---------------------------------------------------------------------------- @@ -398,5 +417,5 @@ pub fn run_wgpu( let event_loop = create_event_loop(&mut native_options); let wgpu_eframe = WgpuWinitApp::new(&event_loop, app_name, native_options, app_creator); - run_and_exit(event_loop, wgpu_eframe); + run_and_exit(event_loop, wgpu_eframe) } diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index 07e36f96b50..3e8cf0e51db 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -357,7 +357,7 @@ impl WinitApp for WgpuWinitApp { fn on_event( &mut self, event_loop: &EventLoopWindowTarget, - event: &winit::event::Event<'_, UserEvent>, + event: &winit::event::Event, ) -> Result { crate::profile_function!(winit_integration::short_event_description(event)); @@ -654,7 +654,7 @@ impl WgpuWinitRunning { fn on_window_event( &mut self, window_id: WindowId, - event: &winit::event::WindowEvent<'_>, + event: &winit::event::WindowEvent, ) -> EventResult { crate::profile_function!(egui_winit::short_window_event_description(event)); @@ -703,18 +703,9 @@ impl WgpuWinitRunning { } } - winit::event::WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - use std::num::NonZeroU32; - if let (Some(width), Some(height), Some(viewport_id)) = ( - NonZeroU32::new(new_inner_size.width), - NonZeroU32::new(new_inner_size.height), - viewport_id, - ) { - repaint_asap = true; - shared.painter.on_window_resized(viewport_id, width, height); - } + winit::event::WindowEvent::ScaleFactorChanged { .. } => { + repaint_asap = true; } - winit::event::WindowEvent::CloseRequested => { if viewport_id == Some(ViewportId::ROOT) && integration.should_close() { log::debug!( @@ -837,9 +828,7 @@ fn create_window( event_loop, native_options, window_settings, - ) - .with_visible(false); // Start hidden until we render the first frame to fix white flash on startup (https://github.com/emilk/egui/pull/3631) - + ); let window = { crate::profile_scope!("WindowBuilder::build"); create_winit_window_builder(egui_ctx, event_loop, viewport_builder.clone()) diff --git a/crates/eframe/src/native/winit_integration.rs b/crates/eframe/src/native/winit_integration.rs index 53de13cc44d..6a2a97b32de 100644 --- a/crates/eframe/src/native/winit_integration.rs +++ b/crates/eframe/src/native/winit_integration.rs @@ -79,7 +79,7 @@ pub trait WinitApp { fn on_event( &mut self, event_loop: &EventLoopWindowTarget, - event: &winit::event::Event<'_, UserEvent>, + event: &winit::event::Event, ) -> crate::Result; } @@ -117,7 +117,7 @@ pub fn system_theme(window: &Window, options: &crate::NativeOptions) -> Option) -> &'static str { +pub fn short_event_description(event: &winit::event::Event) -> &'static str { use winit::event::Event; match event { diff --git a/crates/eframe/src/web/app_runner.rs b/crates/eframe/src/web/app_runner.rs index e8f771bdfda..5a0ead01300 100644 --- a/crates/eframe/src/web/app_runner.rs +++ b/crates/eframe/src/web/app_runner.rs @@ -173,8 +173,20 @@ impl AppRunner { self.painter.destroy(); } - pub fn has_outstanding_paint_data(&self) -> bool { - self.clipped_primitives.is_some() + /// Runs the user code and paints the UI. + /// + /// If there is already an outstanding frame of output, + /// that is painted instead. + pub fn run_and_paint(&mut self) { + if self.clipped_primitives.is_none() { + // Run user code, and paint the results: + self.logic(); + self.paint(); + } else { + // We have already run the logic, e.g. in an on-click event, + // so let's only present the results: + self.paint(); + } } /// Runs the logic, but doesn't paint the result. diff --git a/crates/eframe/src/web/events.rs b/crates/eframe/src/web/events.rs index 9bb5c0f885a..bd8bc88a680 100644 --- a/crates/eframe/src/web/events.rs +++ b/crates/eframe/src/web/events.rs @@ -17,25 +17,8 @@ fn paint_and_schedule(runner_ref: &WebRunner) -> Result<(), JsValue> { fn paint_if_needed(runner: &mut AppRunner) { if runner.needs_repaint.needs_repaint() { - if runner.has_outstanding_paint_data() { - // We have already run the logic, e.g. in an on-click event, - // so let's only present the results: - runner.paint(); - - // We schedule another repaint asap, so that we can run the actual logic - // again, which may schedule a new repaint (if there's animations): - runner.needs_repaint.repaint_asap(); - } else { - // Clear the `needs_repaint` flags _before_ - // running the logic, as the logic could cause it to be set again. - runner.needs_repaint.clear(); - - // Run user code… - runner.logic(); - - // …and paint the result. - runner.paint(); - } + runner.needs_repaint.clear(); + runner.run_and_paint(); } runner.auto_save_if_needed(); } diff --git a/crates/egui-wgpu/Cargo.toml b/crates/egui-wgpu/Cargo.toml index 4fc8d6f986b..5e9d5812d4c 100644 --- a/crates/egui-wgpu/Cargo.toml +++ b/crates/egui-wgpu/Cargo.toml @@ -51,7 +51,7 @@ wgpu.workspace = true ## Enable this when generating docs. document-features = { version = "0.2", optional = true } -winit = { version = "0.28", default-features = false, optional = true } +winit = { version = "0.29", default-features = false, optional = true, features = ["rwh_05"] } # Native: [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/crates/egui-winit/Cargo.toml b/crates/egui-winit/Cargo.toml index 0e0c134a279..6fa007da896 100644 --- a/crates/egui-winit/Cargo.toml +++ b/crates/egui-winit/Cargo.toml @@ -61,12 +61,12 @@ egui = { version = "0.24.0", path = "../egui", default-features = false, feature log = { version = "0.4", features = ["std"] } raw-window-handle.workspace = true web-time = { version = "0.2" } # We use web-time so we can (maybe) compile for web -winit = { version = "0.28", default-features = false } +winit = { version = "0.29.4", default-features = false, features = ["rwh_05"] } #! ### Optional dependencies # feature accesskit -accesskit_winit = { version = "0.15.0", optional = true } +accesskit_winit = { version = "0.16.0", optional = true } ## Enable this when generating docs. document-features = { version = "0.2", optional = true } diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index e00083c5a13..ffc1e247efe 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -232,7 +232,7 @@ impl State { pub fn on_window_event( &mut self, egui_ctx: &egui::Context, - event: &winit::event::WindowEvent<'_>, + event: &winit::event::WindowEvent, ) -> EventResponse { crate::profile_function!(short_window_event_description(event)); @@ -295,25 +295,6 @@ impl State { consumed, } } - WindowEvent::ReceivedCharacter(ch) => { - // On Mac we get here when the user presses Cmd-C (copy), ctrl-W, etc. - // We need to ignore these characters that are side-effects of commands. - let is_mac_cmd = cfg!(target_os = "macos") - && (self.egui_input.modifiers.ctrl || self.egui_input.modifiers.mac_cmd); - - let consumed = if is_printable_char(*ch) && !is_mac_cmd { - self.egui_input - .events - .push(egui::Event::Text(ch.to_string())); - egui_ctx.wants_keyboard_input() - } else { - false - }; - EventResponse { - repaint: true, - consumed, - } - } WindowEvent::Ime(ime) => { // on Mac even Cmd-C is pressed during ime, a `c` is pushed to Preedit. // So no need to check is_mac_cmd. @@ -353,11 +334,12 @@ impl State { consumed: egui_ctx.wants_keyboard_input(), } } - WindowEvent::KeyboardInput { input, .. } => { - self.on_keyboard_input(input); + WindowEvent::KeyboardInput { event, .. } => { // When pressing the Tab key, egui focuses the first focusable element, hence Tab always consumes. - let consumed = egui_ctx.wants_keyboard_input() - || input.virtual_keycode == Some(winit::event::VirtualKeyCode::Tab); + let consumed = self.on_keyboard_input(event) + || egui_ctx.wants_keyboard_input() + || event.logical_key + == winit::keyboard::Key::Named(winit::keyboard::NamedKey::Tab); EventResponse { repaint: true, consumed, @@ -405,14 +387,20 @@ impl State { } } WindowEvent::ModifiersChanged(state) => { - self.egui_input.modifiers.alt = state.alt(); - self.egui_input.modifiers.ctrl = state.ctrl(); - self.egui_input.modifiers.shift = state.shift(); - self.egui_input.modifiers.mac_cmd = cfg!(target_os = "macos") && state.logo(); + use winit::keyboard::ModifiersKeyState::Pressed; + self.egui_input.modifiers.alt = + state.lalt_state() == Pressed || state.ralt_state() == Pressed; + self.egui_input.modifiers.ctrl = + state.lcontrol_state() == Pressed || state.rcontrol_state() == Pressed; + self.egui_input.modifiers.shift = + state.lshift_state() == Pressed || state.rshift_state() == Pressed; + self.egui_input.modifiers.mac_cmd = cfg!(target_os = "macos") + && (state.lsuper_state() == Pressed || state.rsuper_state() == Pressed); + self.egui_input.modifiers.command = if cfg!(target_os = "macos") { - state.logo() + state.lsuper_state() == Pressed || state.rsuper_state() == Pressed } else { - state.ctrl() + state.lcontrol_state() == Pressed || state.rcontrol_state() == Pressed }; EventResponse { repaint: true, @@ -421,20 +409,26 @@ impl State { } // Things that may require repaint: - WindowEvent::CursorEntered { .. } + WindowEvent::CloseRequested => EventResponse { + consumed: true, + repaint: true, + }, + + WindowEvent::RedrawRequested + | WindowEvent::CursorEntered { .. } | WindowEvent::Destroyed | WindowEvent::Occluded(_) | WindowEvent::Resized(_) | WindowEvent::Moved(_) | WindowEvent::ThemeChanged(_) - | WindowEvent::TouchpadPressure { .. } - | WindowEvent::CloseRequested => EventResponse { + | WindowEvent::TouchpadPressure { .. } => EventResponse { repaint: true, consumed: false, }, // Things we completely ignore: - WindowEvent::AxisMotion { .. } + WindowEvent::ActivationTokenDone { .. } + | WindowEvent::AxisMotion { .. } | WindowEvent::SmartMagnify { .. } | WindowEvent::TouchpadRotate { .. } => EventResponse { repaint: false, @@ -645,17 +639,19 @@ impl State { } } - fn on_keyboard_input(&mut self, input: &winit::event::KeyboardInput) { - if let Some(keycode) = input.virtual_keycode { + fn on_keyboard_input(&mut self, input: &winit::event::KeyEvent) -> bool { + if let winit::keyboard::PhysicalKey::Code(keycode) = input.physical_key { let pressed = input.state == winit::event::ElementState::Pressed; if pressed { - // VirtualKeyCode::Paste etc in winit are broken/untrustworthy, + // KeyCode::Paste etc in winit are broken/untrustworthy, // so we detect these things manually: if is_cut_command(self.egui_input.modifiers, keycode) { self.egui_input.events.push(egui::Event::Cut); + return true; } else if is_copy_command(self.egui_input.modifiers, keycode) { self.egui_input.events.push(egui::Event::Copy); + return true; } else if is_paste_command(self.egui_input.modifiers, keycode) { if let Some(contents) = self.clipboard.get() { let contents = contents.replace("\r\n", "\n"); @@ -663,10 +659,11 @@ impl State { self.egui_input.events.push(egui::Event::Paste(contents)); } } + return true; } } - if let Some(key) = translate_virtual_key_code(keycode) { + if let Some(key) = translate_key_code(keycode) { self.egui_input.events.push(egui::Event::Key { key, pressed, @@ -675,6 +672,14 @@ impl State { }); } } + + if let Some(text) = &input.text { + self.egui_input + .events + .push(egui::Event::Text(text.to_string())); + } + + false } /// Call with the output given by `egui`. @@ -723,7 +728,14 @@ impl State { } if let Some(egui::Pos2 { x, y }) = text_cursor_pos { - window.set_ime_position(winit::dpi::LogicalPosition { x, y }); + window.set_ime_cursor_area( + winit::dpi::LogicalPosition { x, y }, + winit::dpi::LogicalSize { + // TODO: What size to use? New size arg in winit 0.29 + width: 10, + height: 10, + }, + ); } #[cfg(feature = "accesskit")] @@ -852,37 +864,25 @@ fn open_url_in_browser(_url: &str) { } } -/// Winit sends special keys (backspace, delete, F1, …) as characters. -/// Ignore those. -/// We also ignore '\r', '\n', '\t'. -/// Newlines are handled by the `Key::Enter` event. -fn is_printable_char(chr: char) -> bool { - let is_in_private_use_area = '\u{e000}' <= chr && chr <= '\u{f8ff}' - || '\u{f0000}' <= chr && chr <= '\u{ffffd}' - || '\u{100000}' <= chr && chr <= '\u{10fffd}'; - - !is_in_private_use_area && !chr.is_ascii_control() -} - -fn is_cut_command(modifiers: egui::Modifiers, keycode: winit::event::VirtualKeyCode) -> bool { - (modifiers.command && keycode == winit::event::VirtualKeyCode::X) +fn is_cut_command(modifiers: egui::Modifiers, keycode: winit::keyboard::KeyCode) -> bool { + (modifiers.command && keycode == winit::keyboard::KeyCode::KeyX) || (cfg!(target_os = "windows") && modifiers.shift - && keycode == winit::event::VirtualKeyCode::Delete) + && keycode == winit::keyboard::KeyCode::Delete) } -fn is_copy_command(modifiers: egui::Modifiers, keycode: winit::event::VirtualKeyCode) -> bool { - (modifiers.command && keycode == winit::event::VirtualKeyCode::C) +fn is_copy_command(modifiers: egui::Modifiers, keycode: winit::keyboard::KeyCode) -> bool { + (modifiers.command && keycode == winit::keyboard::KeyCode::KeyC) || (cfg!(target_os = "windows") && modifiers.ctrl - && keycode == winit::event::VirtualKeyCode::Insert) + && keycode == winit::keyboard::KeyCode::Insert) } -fn is_paste_command(modifiers: egui::Modifiers, keycode: winit::event::VirtualKeyCode) -> bool { - (modifiers.command && keycode == winit::event::VirtualKeyCode::V) +fn is_paste_command(modifiers: egui::Modifiers, keycode: winit::keyboard::KeyCode) -> bool { + (modifiers.command && keycode == winit::keyboard::KeyCode::KeyV) || (cfg!(target_os = "windows") && modifiers.shift - && keycode == winit::event::VirtualKeyCode::Insert) + && keycode == winit::keyboard::KeyCode::Insert) } fn translate_mouse_button(button: winit::event::MouseButton) -> Option { @@ -890,100 +890,99 @@ fn translate_mouse_button(button: winit::event::MouseButton) -> Option Some(egui::PointerButton::Primary), winit::event::MouseButton::Right => Some(egui::PointerButton::Secondary), winit::event::MouseButton::Middle => Some(egui::PointerButton::Middle), - winit::event::MouseButton::Other(1) => Some(egui::PointerButton::Extra1), - winit::event::MouseButton::Other(2) => Some(egui::PointerButton::Extra2), + winit::event::MouseButton::Back => Some(egui::PointerButton::Extra1), + winit::event::MouseButton::Forward => Some(egui::PointerButton::Extra2), winit::event::MouseButton::Other(_) => None, } } -fn translate_virtual_key_code(key: winit::event::VirtualKeyCode) -> Option { +fn translate_key_code(key: winit::keyboard::KeyCode) -> Option { use egui::Key; - use winit::event::VirtualKeyCode; + use winit::keyboard::KeyCode; Some(match key { - VirtualKeyCode::Down => Key::ArrowDown, - VirtualKeyCode::Left => Key::ArrowLeft, - VirtualKeyCode::Right => Key::ArrowRight, - VirtualKeyCode::Up => Key::ArrowUp, - - VirtualKeyCode::Escape => Key::Escape, - VirtualKeyCode::Tab => Key::Tab, - VirtualKeyCode::Back => Key::Backspace, - VirtualKeyCode::Return | VirtualKeyCode::NumpadEnter => Key::Enter, - VirtualKeyCode::Space => Key::Space, - - VirtualKeyCode::Insert => Key::Insert, - VirtualKeyCode::Delete => Key::Delete, - VirtualKeyCode::Home => Key::Home, - VirtualKeyCode::End => Key::End, - VirtualKeyCode::PageUp => Key::PageUp, - VirtualKeyCode::PageDown => Key::PageDown, - - VirtualKeyCode::Minus | VirtualKeyCode::NumpadSubtract => Key::Minus, + KeyCode::ArrowDown => Key::ArrowDown, + KeyCode::ArrowLeft => Key::ArrowLeft, + KeyCode::ArrowRight => Key::ArrowRight, + KeyCode::ArrowUp => Key::ArrowUp, + + KeyCode::Escape => Key::Escape, + KeyCode::Tab => Key::Tab, + KeyCode::Backspace => Key::Backspace, + KeyCode::Enter | KeyCode::NumpadEnter => Key::Enter, + KeyCode::Space => Key::Space, + + KeyCode::Insert => Key::Insert, + KeyCode::Delete => Key::Delete, + KeyCode::Home => Key::Home, + KeyCode::End => Key::End, + KeyCode::PageUp => Key::PageUp, + KeyCode::PageDown => Key::PageDown, + + KeyCode::Minus | KeyCode::NumpadSubtract => Key::Minus, + // Using Mac the key with the Plus sign on it is reported as the Equals key // (with both English and Swedish keyboard). - VirtualKeyCode::Equals | VirtualKeyCode::Plus | VirtualKeyCode::NumpadAdd => { - Key::PlusEquals - } - - VirtualKeyCode::Key0 | VirtualKeyCode::Numpad0 => Key::Num0, - VirtualKeyCode::Key1 | VirtualKeyCode::Numpad1 => Key::Num1, - VirtualKeyCode::Key2 | VirtualKeyCode::Numpad2 => Key::Num2, - VirtualKeyCode::Key3 | VirtualKeyCode::Numpad3 => Key::Num3, - VirtualKeyCode::Key4 | VirtualKeyCode::Numpad4 => Key::Num4, - VirtualKeyCode::Key5 | VirtualKeyCode::Numpad5 => Key::Num5, - VirtualKeyCode::Key6 | VirtualKeyCode::Numpad6 => Key::Num6, - VirtualKeyCode::Key7 | VirtualKeyCode::Numpad7 => Key::Num7, - VirtualKeyCode::Key8 | VirtualKeyCode::Numpad8 => Key::Num8, - VirtualKeyCode::Key9 | VirtualKeyCode::Numpad9 => Key::Num9, - - VirtualKeyCode::A => Key::A, - VirtualKeyCode::B => Key::B, - VirtualKeyCode::C => Key::C, - VirtualKeyCode::D => Key::D, - VirtualKeyCode::E => Key::E, - VirtualKeyCode::F => Key::F, - VirtualKeyCode::G => Key::G, - VirtualKeyCode::H => Key::H, - VirtualKeyCode::I => Key::I, - VirtualKeyCode::J => Key::J, - VirtualKeyCode::K => Key::K, - VirtualKeyCode::L => Key::L, - VirtualKeyCode::M => Key::M, - VirtualKeyCode::N => Key::N, - VirtualKeyCode::O => Key::O, - VirtualKeyCode::P => Key::P, - VirtualKeyCode::Q => Key::Q, - VirtualKeyCode::R => Key::R, - VirtualKeyCode::S => Key::S, - VirtualKeyCode::T => Key::T, - VirtualKeyCode::U => Key::U, - VirtualKeyCode::V => Key::V, - VirtualKeyCode::W => Key::W, - VirtualKeyCode::X => Key::X, - VirtualKeyCode::Y => Key::Y, - VirtualKeyCode::Z => Key::Z, - - VirtualKeyCode::F1 => Key::F1, - VirtualKeyCode::F2 => Key::F2, - VirtualKeyCode::F3 => Key::F3, - VirtualKeyCode::F4 => Key::F4, - VirtualKeyCode::F5 => Key::F5, - VirtualKeyCode::F6 => Key::F6, - VirtualKeyCode::F7 => Key::F7, - VirtualKeyCode::F8 => Key::F8, - VirtualKeyCode::F9 => Key::F9, - VirtualKeyCode::F10 => Key::F10, - VirtualKeyCode::F11 => Key::F11, - VirtualKeyCode::F12 => Key::F12, - VirtualKeyCode::F13 => Key::F13, - VirtualKeyCode::F14 => Key::F14, - VirtualKeyCode::F15 => Key::F15, - VirtualKeyCode::F16 => Key::F16, - VirtualKeyCode::F17 => Key::F17, - VirtualKeyCode::F18 => Key::F18, - VirtualKeyCode::F19 => Key::F19, - VirtualKeyCode::F20 => Key::F20, + KeyCode::Equal | KeyCode::NumpadAdd => Key::PlusEquals, + + KeyCode::Digit0 | KeyCode::Numpad0 => Key::Num0, + KeyCode::Digit1 | KeyCode::Numpad1 => Key::Num1, + KeyCode::Digit2 | KeyCode::Numpad2 => Key::Num2, + KeyCode::Digit3 | KeyCode::Numpad3 => Key::Num3, + KeyCode::Digit4 | KeyCode::Numpad4 => Key::Num4, + KeyCode::Digit5 | KeyCode::Numpad5 => Key::Num5, + KeyCode::Digit6 | KeyCode::Numpad6 => Key::Num6, + KeyCode::Digit7 | KeyCode::Numpad7 => Key::Num7, + KeyCode::Digit8 | KeyCode::Numpad8 => Key::Num8, + KeyCode::Digit9 | KeyCode::Numpad9 => Key::Num9, + + KeyCode::KeyA => Key::A, + KeyCode::KeyB => Key::B, + KeyCode::KeyC => Key::C, + KeyCode::KeyD => Key::D, + KeyCode::KeyE => Key::E, + KeyCode::KeyF => Key::F, + KeyCode::KeyG => Key::G, + KeyCode::KeyH => Key::H, + KeyCode::KeyI => Key::I, + KeyCode::KeyJ => Key::J, + KeyCode::KeyK => Key::K, + KeyCode::KeyL => Key::L, + KeyCode::KeyM => Key::M, + KeyCode::KeyN => Key::N, + KeyCode::KeyO => Key::O, + KeyCode::KeyP => Key::P, + KeyCode::KeyQ => Key::Q, + KeyCode::KeyR => Key::R, + KeyCode::KeyS => Key::S, + KeyCode::KeyT => Key::T, + KeyCode::KeyU => Key::U, + KeyCode::KeyV => Key::V, + KeyCode::KeyW => Key::W, + KeyCode::KeyX => Key::X, + KeyCode::KeyY => Key::Y, + KeyCode::KeyZ => Key::Z, + + KeyCode::F1 => Key::F1, + KeyCode::F2 => Key::F2, + KeyCode::F3 => Key::F3, + KeyCode::F4 => Key::F4, + KeyCode::F5 => Key::F5, + KeyCode::F6 => Key::F6, + KeyCode::F7 => Key::F7, + KeyCode::F8 => Key::F8, + KeyCode::F9 => Key::F9, + KeyCode::F10 => Key::F10, + KeyCode::F11 => Key::F11, + KeyCode::F12 => Key::F12, + KeyCode::F13 => Key::F13, + KeyCode::F14 => Key::F14, + KeyCode::F15 => Key::F15, + KeyCode::F16 => Key::F16, + KeyCode::F17 => Key::F17, + KeyCode::F18 => Key::F18, + KeyCode::F19 => Key::F19, + KeyCode::F20 => Key::F20, _ => { return None; @@ -1008,7 +1007,7 @@ fn translate_cursor(cursor_icon: egui::CursorIcon) -> Option Some(winit::window::CursorIcon::Move), egui::CursorIcon::NoDrop => Some(winit::window::CursorIcon::NoDrop), egui::CursorIcon::NotAllowed => Some(winit::window::CursorIcon::NotAllowed), - egui::CursorIcon::PointingHand => Some(winit::window::CursorIcon::Hand), + egui::CursorIcon::PointingHand => Some(winit::window::CursorIcon::Pointer), egui::CursorIcon::Progress => Some(winit::window::CursorIcon::Progress), egui::CursorIcon::ResizeHorizontal => Some(winit::window::CursorIcon::EwResize), @@ -1097,7 +1096,7 @@ fn process_viewport_command( ViewportCommand::InnerSize(size) => { let width_px = pixels_per_point * size.x.max(1.0); let height_px = pixels_per_point * size.y.max(1.0); - window.set_inner_size(PhysicalSize::new(width_px, height_px)); + let _ = window.request_inner_size(PhysicalSize::new(width_px, height_px)); } ViewportCommand::BeginResize(direction) => { if let Err(err) = window.drag_resize_window(match direction { @@ -1182,10 +1181,10 @@ fn process_viewport_command( })); } ViewportCommand::IMEPosition(pos) => { - window.set_ime_position(PhysicalPosition::new( - pixels_per_point * pos.x, - pixels_per_point * pos.y, - )); + window.set_ime_cursor_area( + PhysicalPosition::new(pixels_per_point * pos.x, pixels_per_point * pos.y), + PhysicalSize::new(100, 100), + ); } ViewportCommand::IMEAllowed(v) => window.set_ime_allowed(v), ViewportCommand::IMEPurpose(p) => window.set_ime_purpose(match p { @@ -1403,16 +1402,15 @@ pub fn apply_viewport_builder_to_new_window(window: &Window, builder: &ViewportB /// Short and fast description of an event. /// Useful for logging and profiling. -pub fn short_generic_event_description(event: &winit::event::Event<'_, T>) -> &'static str { +pub fn short_generic_event_description(event: &winit::event::Event) -> &'static str { use winit::event::{DeviceEvent, Event, StartCause}; match event { + Event::AboutToWait => "Event::AboutToWait", + Event::LoopExiting => "Event::LoopExiting", Event::Suspended => "Event::Suspended", Event::Resumed => "Event::Resumed", - Event::MainEventsCleared => "Event::MainEventsCleared", - Event::RedrawRequested(_) => "Event::RedrawRequested", - Event::RedrawEventsCleared => "Event::RedrawEventsCleared", - Event::LoopDestroyed => "Event::LoopDestroyed", + Event::MemoryWarning => "Event::MemoryWarning", Event::UserEvent(_) => "UserEvent", Event::DeviceEvent { event, .. } => match event { DeviceEvent::Added { .. } => "DeviceEvent::Added", @@ -1422,7 +1420,6 @@ pub fn short_generic_event_description(event: &winit::event::Event<'_, T>) -> DeviceEvent::Motion { .. } => "DeviceEvent::Motion", DeviceEvent::Button { .. } => "DeviceEvent::Button", DeviceEvent::Key { .. } => "DeviceEvent::Key", - DeviceEvent::Text { .. } => "DeviceEvent::Text", }, Event::NewEvents(start_cause) => match start_cause { StartCause::ResumeTimeReached { .. } => "NewEvents::ResumeTimeReached", @@ -1436,10 +1433,11 @@ pub fn short_generic_event_description(event: &winit::event::Event<'_, T>) -> /// Short and fast description of an event. /// Useful for logging and profiling. -pub fn short_window_event_description(event: &winit::event::WindowEvent<'_>) -> &'static str { +pub fn short_window_event_description(event: &winit::event::WindowEvent) -> &'static str { use winit::event::WindowEvent; match event { + WindowEvent::ActivationTokenDone { .. } => "WindowEvent::ActivationTokenDone", WindowEvent::Resized { .. } => "WindowEvent::Resized", WindowEvent::Moved { .. } => "WindowEvent::Moved", WindowEvent::CloseRequested { .. } => "WindowEvent::CloseRequested", @@ -1447,7 +1445,6 @@ pub fn short_window_event_description(event: &winit::event::WindowEvent<'_>) -> WindowEvent::DroppedFile { .. } => "WindowEvent::DroppedFile", WindowEvent::HoveredFile { .. } => "WindowEvent::HoveredFile", WindowEvent::HoveredFileCancelled { .. } => "WindowEvent::HoveredFileCancelled", - WindowEvent::ReceivedCharacter { .. } => "WindowEvent::ReceivedCharacter", WindowEvent::Focused { .. } => "WindowEvent::Focused", WindowEvent::KeyboardInput { .. } => "WindowEvent::KeyboardInput", WindowEvent::ModifiersChanged { .. } => "WindowEvent::ModifiersChanged", @@ -1458,6 +1455,7 @@ pub fn short_window_event_description(event: &winit::event::WindowEvent<'_>) -> WindowEvent::MouseWheel { .. } => "WindowEvent::MouseWheel", WindowEvent::MouseInput { .. } => "WindowEvent::MouseInput", WindowEvent::TouchpadMagnify { .. } => "WindowEvent::TouchpadMagnify", + WindowEvent::RedrawRequested { .. } => "WindowEvent::RedrawRequested", WindowEvent::SmartMagnify { .. } => "WindowEvent::SmartMagnify", WindowEvent::TouchpadRotate { .. } => "WindowEvent::TouchpadRotate", WindowEvent::TouchpadPressure { .. } => "WindowEvent::TouchpadPressure", diff --git a/crates/egui/src/viewport.rs b/crates/egui/src/viewport.rs index 45d2e535324..d10d13897f8 100644 --- a/crates/egui/src/viewport.rs +++ b/crates/egui/src/viewport.rs @@ -255,7 +255,7 @@ pub type ImmediateViewportRendererCallback = dyn for<'a> Fn(&Context, ImmediateV #[derive(Clone, Debug, Default, Eq, PartialEq)] #[allow(clippy::option_option)] pub struct ViewportBuilder { - /// The title of the viewport. + /// The title of the vieweport. /// `eframe` will use this as the title of the native window. pub title: Option, diff --git a/crates/egui_demo_app/Cargo.toml b/crates/egui_demo_app/Cargo.toml index 6fe18445629..1dd9ccd59dc 100644 --- a/crates/egui_demo_app/Cargo.toml +++ b/crates/egui_demo_app/Cargo.toml @@ -77,6 +77,6 @@ rfd = { version = "0.11", optional = true } # web: [target.'cfg(target_arch = "wasm32")'.dependencies] -wasm-bindgen = "=0.2.89" +wasm-bindgen = "=0.2.88" wasm-bindgen-futures = "0.4" web-sys = "0.3" diff --git a/crates/egui_glow/Cargo.toml b/crates/egui_glow/Cargo.toml index 28b4590df2f..8603b5e926e 100644 --- a/crates/egui_glow/Cargo.toml +++ b/crates/egui_glow/Cargo.toml @@ -69,9 +69,9 @@ wasm-bindgen = "0.2" [dev-dependencies] -glutin = "0.30" # examples/pure_glow +glutin = "0.31" # examples/pure_glow raw-window-handle.workspace = true -glutin-winit = "0.3.0" +glutin-winit = "0.4.0" [[example]] diff --git a/crates/egui_glow/examples/pure_glow.rs b/crates/egui_glow/examples/pure_glow.rs index 5709a4d03e6..f9949d3fb7d 100644 --- a/crates/egui_glow/examples/pure_glow.rs +++ b/crates/egui_glow/examples/pure_glow.rs @@ -19,7 +19,7 @@ impl GlutinWindowContext { #[allow(unsafe_code)] unsafe fn new(event_loop: &winit::event_loop::EventLoopWindowTarget) -> Self { use egui::NumExt; - use glutin::context::NotCurrentGlContextSurfaceAccessor; + use glutin::context::NotCurrentGlContext; use glutin::display::GetGlDisplay; use glutin::display::GlDisplay; use glutin::prelude::GlSurface; @@ -42,7 +42,7 @@ impl GlutinWindowContext { log::debug!("trying to get gl_config"); let (mut window, gl_config) = glutin_winit::DisplayBuilder::new() // let glutin-winit helper crate handle the complex parts of opengl context creation - .with_preference(glutin_winit::ApiPrefence::FallbackEgl) // https://github.com/emilk/egui/issues/2520#issuecomment-1367841150 + .with_preference(glutin_winit::ApiPreference::FallbackEgl) // https://github.com/emilk/egui/issues/2520#issuecomment-1367841150 .with_window_builder(Some(winit_window_builder.clone())) .build( event_loop, @@ -150,7 +150,9 @@ pub enum UserEvent { fn main() { let mut clear_color = [0.1, 0.1, 0.1]; - let event_loop = winit::event_loop::EventLoopBuilder::::with_user_event().build(); + let event_loop = winit::event_loop::EventLoopBuilder::::with_user_event() + .build() + .unwrap(); let (gl_window, gl) = create_display(&event_loop); let gl = std::rc::Rc::new(gl); @@ -168,7 +170,7 @@ fn main() { let mut repaint_delay = std::time::Duration::MAX; - event_loop.run(move |event, _, control_flow| { + let _ = event_loop.run(move |event, event_loop_window_target| { let mut redraw = || { let mut quit = false; @@ -182,18 +184,20 @@ fn main() { }); }); - *control_flow = if quit { - winit::event_loop::ControlFlow::Exit - } else if repaint_delay.is_zero() { - gl_window.window().request_redraw(); - winit::event_loop::ControlFlow::Poll - } else if let Some(repaint_delay_instant) = - std::time::Instant::now().checked_add(repaint_delay) - { - winit::event_loop::ControlFlow::WaitUntil(repaint_delay_instant) + if quit { + event_loop_window_target.exit(); } else { - winit::event_loop::ControlFlow::Wait - }; + event_loop_window_target.set_control_flow(if repaint_delay.is_zero() { + gl_window.window().request_redraw(); + winit::event_loop::ControlFlow::Poll + } else if let Some(repaint_after_instant) = + std::time::Instant::now().checked_add(repaint_delay) + { + winit::event_loop::ControlFlow::WaitUntil(repaint_after_instant) + } else { + winit::event_loop::ControlFlow::Wait + }); + } { unsafe { @@ -217,22 +221,23 @@ fn main() { // Platform-dependent event handlers to workaround a winit bug // See: https://github.com/rust-windowing/winit/issues/987 // See: https://github.com/rust-windowing/winit/issues/1619 - winit::event::Event::RedrawEventsCleared if cfg!(target_os = "windows") => redraw(), - winit::event::Event::RedrawRequested(_) if !cfg!(target_os = "windows") => redraw(), - + // winit::event::Event::RedrawEventsCleared if cfg!(target_os = "windows") => redraw(), + // winit::event::Event::RedrawRequested(_) if !cfg!(target_os = "windows") => redraw(), + // TODO: Adopt to above comment (if still relevant) winit::event::Event::WindowEvent { event, .. } => { use winit::event::WindowEvent; if matches!(event, WindowEvent::CloseRequested | WindowEvent::Destroyed) { - *control_flow = winit::event_loop::ControlFlow::Exit; + event_loop_window_target.exit(); + return; + } + + if matches!(event, WindowEvent::RedrawRequested) { + redraw(); + return; } if let winit::event::WindowEvent::Resized(physical_size) = &event { gl_window.resize(*physical_size); - } else if let winit::event::WindowEvent::ScaleFactorChanged { - new_inner_size, .. - } = &event - { - gl_window.resize(**new_inner_size); } let event_response = egui_glow.on_window_event(&event); @@ -245,7 +250,7 @@ fn main() { winit::event::Event::UserEvent(UserEvent::Redraw(delay)) => { repaint_delay = delay; } - winit::event::Event::LoopDestroyed => { + winit::event::Event::LoopExiting => { egui_glow.destroy(); } winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached { diff --git a/crates/egui_glow/src/winit.rs b/crates/egui_glow/src/winit.rs index 1ec54856b82..f9ec6ee9396 100644 --- a/crates/egui_glow/src/winit.rs +++ b/crates/egui_glow/src/winit.rs @@ -53,7 +53,7 @@ impl EguiGlow { } } - pub fn on_window_event(&mut self, event: &winit::event::WindowEvent<'_>) -> EventResponse { + pub fn on_window_event(&mut self, event: &winit::event::WindowEvent) -> EventResponse { self.egui_winit.on_window_event(&self.egui_ctx, event) } From c8637145a47cdb19b2176b1b29c34df44decced2 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Mon, 27 Nov 2023 23:07:18 +0100 Subject: [PATCH 02/46] Use 0.29.4 also in eframe and egui-wgpu --- crates/eframe/Cargo.toml | 2 +- crates/egui-wgpu/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/eframe/Cargo.toml b/crates/eframe/Cargo.toml index 0178b0964b9..0c37b5ffdc4 100644 --- a/crates/eframe/Cargo.toml +++ b/crates/eframe/Cargo.toml @@ -127,7 +127,7 @@ image = { version = "0.24", default-features = false, features = [ "png", ] } # Needed for app icon raw-window-handle.workspace = true -winit = { version = "0.29", default-features = false, features = ["rwh_05"] } +winit = { version = "0.29.4", default-features = false, features = ["rwh_05"] } # optional native: directories-next = { version = "2", optional = true } diff --git a/crates/egui-wgpu/Cargo.toml b/crates/egui-wgpu/Cargo.toml index 5e9d5812d4c..e4500ca1d4e 100644 --- a/crates/egui-wgpu/Cargo.toml +++ b/crates/egui-wgpu/Cargo.toml @@ -51,7 +51,7 @@ wgpu.workspace = true ## Enable this when generating docs. document-features = { version = "0.2", optional = true } -winit = { version = "0.29", default-features = false, optional = true, features = ["rwh_05"] } +winit = { version = "0.29.4", default-features = false, optional = true, features = ["rwh_05"] } # Native: [target.'cfg(not(target_arch = "wasm32"))'.dependencies] From fc433721b56a699598801a9c9bd031234d68bc9f Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Mon, 27 Nov 2023 23:13:14 +0100 Subject: [PATCH 03/46] Revert accidental change --- crates/eframe/src/native/glow_integration.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index 0041a2d7593..95d1a44339f 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -155,7 +155,8 @@ impl GlowWinitApp { event_loop, native_options, window_settings, - ); + ) + .with_visible(false); // Start hidden until we render the first frame to fix white flash on startup (https://github.com/emilk/egui/pull/3631) let mut glutin_window_context = unsafe { GlutinWindowContext::new(egui_ctx, winit_window_builder, native_options, event_loop)? From 12a27ce74f3ff6f6f1437763e8018eb1e209bf15 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Mon, 27 Nov 2023 23:16:10 +0100 Subject: [PATCH 04/46] Fix accidental change --- crates/eframe/src/native/wgpu_integration.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index 3e8cf0e51db..b748dbcf0d7 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -828,7 +828,8 @@ fn create_window( event_loop, native_options, window_settings, - ); + ) + .with_visible(false); // Start hidden until we render the first frame to fix white flash on startup (https://github.com/emilk/egui/pull/3631) let window = { crate::profile_scope!("WindowBuilder::build"); create_winit_window_builder(egui_ctx, event_loop, viewport_builder.clone()) From 7746482281d2ad5487c5923cd33dabef030093dd Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Mon, 27 Nov 2023 23:16:55 +0100 Subject: [PATCH 05/46] Revert empty line removal --- crates/eframe/src/native/wgpu_integration.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index b748dbcf0d7..473d5b8ecd5 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -830,6 +830,7 @@ fn create_window( window_settings, ) .with_visible(false); // Start hidden until we render the first frame to fix white flash on startup (https://github.com/emilk/egui/pull/3631) + let window = { crate::profile_scope!("WindowBuilder::build"); create_winit_window_builder(egui_ctx, event_loop, viewport_builder.clone()) From 3eb6d91ebed56f94489c6a1b9e9235fb81270bde Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Mon, 27 Nov 2023 23:18:24 +0100 Subject: [PATCH 06/46] Fix accidental commit reversal --- crates/eframe/src/web/app_runner.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/crates/eframe/src/web/app_runner.rs b/crates/eframe/src/web/app_runner.rs index 5a0ead01300..e8f771bdfda 100644 --- a/crates/eframe/src/web/app_runner.rs +++ b/crates/eframe/src/web/app_runner.rs @@ -173,20 +173,8 @@ impl AppRunner { self.painter.destroy(); } - /// Runs the user code and paints the UI. - /// - /// If there is already an outstanding frame of output, - /// that is painted instead. - pub fn run_and_paint(&mut self) { - if self.clipped_primitives.is_none() { - // Run user code, and paint the results: - self.logic(); - self.paint(); - } else { - // We have already run the logic, e.g. in an on-click event, - // so let's only present the results: - self.paint(); - } + pub fn has_outstanding_paint_data(&self) -> bool { + self.clipped_primitives.is_some() } /// Runs the logic, but doesn't paint the result. From e5d5076396fc52afd773432c76c99afffd278989 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Mon, 27 Nov 2023 23:20:15 +0100 Subject: [PATCH 07/46] Fix accidental commit reversal --- crates/egui/src/viewport.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/egui/src/viewport.rs b/crates/egui/src/viewport.rs index d10d13897f8..45d2e535324 100644 --- a/crates/egui/src/viewport.rs +++ b/crates/egui/src/viewport.rs @@ -255,7 +255,7 @@ pub type ImmediateViewportRendererCallback = dyn for<'a> Fn(&Context, ImmediateV #[derive(Clone, Debug, Default, Eq, PartialEq)] #[allow(clippy::option_option)] pub struct ViewportBuilder { - /// The title of the vieweport. + /// The title of the viewport. /// `eframe` will use this as the title of the native window. pub title: Option, From 258e49f446f217f3dfa77ffbcf856424ba054c49 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Mon, 27 Nov 2023 23:22:48 +0100 Subject: [PATCH 08/46] Revert accidental change --- crates/egui_demo_app/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/egui_demo_app/Cargo.toml b/crates/egui_demo_app/Cargo.toml index 1dd9ccd59dc..6fe18445629 100644 --- a/crates/egui_demo_app/Cargo.toml +++ b/crates/egui_demo_app/Cargo.toml @@ -77,6 +77,6 @@ rfd = { version = "0.11", optional = true } # web: [target.'cfg(target_arch = "wasm32")'.dependencies] -wasm-bindgen = "=0.2.88" +wasm-bindgen = "=0.2.89" wasm-bindgen-futures = "0.4" web-sys = "0.3" From 2191a3b4dc24cdbed9153005fb8217d88e35dc15 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Mon, 27 Nov 2023 23:24:22 +0100 Subject: [PATCH 09/46] Fix accidental reversal --- crates/eframe/src/web/events.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/eframe/src/web/events.rs b/crates/eframe/src/web/events.rs index bd8bc88a680..9bb5c0f885a 100644 --- a/crates/eframe/src/web/events.rs +++ b/crates/eframe/src/web/events.rs @@ -17,8 +17,25 @@ fn paint_and_schedule(runner_ref: &WebRunner) -> Result<(), JsValue> { fn paint_if_needed(runner: &mut AppRunner) { if runner.needs_repaint.needs_repaint() { - runner.needs_repaint.clear(); - runner.run_and_paint(); + if runner.has_outstanding_paint_data() { + // We have already run the logic, e.g. in an on-click event, + // so let's only present the results: + runner.paint(); + + // We schedule another repaint asap, so that we can run the actual logic + // again, which may schedule a new repaint (if there's animations): + runner.needs_repaint.repaint_asap(); + } else { + // Clear the `needs_repaint` flags _before_ + // running the logic, as the logic could cause it to be set again. + runner.needs_repaint.clear(); + + // Run user code… + runner.logic(); + + // …and paint the result. + runner.paint(); + } } runner.auto_save_if_needed(); } From fc2c14262c9740c1bc21e24f24aa313375ed9ee2 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Mon, 27 Nov 2023 23:39:11 +0100 Subject: [PATCH 10/46] Fix accidental reversal --- Cargo.lock | 20 ++++++++++---------- crates/egui-winit/src/lib.rs | 8 ++------ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fcbe104c417..70579803f0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4398,9 +4398,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4408,9 +4408,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", @@ -4435,9 +4435,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4445,9 +4445,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", @@ -4458,9 +4458,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "wayland-backend" diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index ffc1e247efe..406a84fed5a 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -409,11 +409,6 @@ impl State { } // Things that may require repaint: - WindowEvent::CloseRequested => EventResponse { - consumed: true, - repaint: true, - }, - WindowEvent::RedrawRequested | WindowEvent::CursorEntered { .. } | WindowEvent::Destroyed @@ -421,7 +416,8 @@ impl State { | WindowEvent::Resized(_) | WindowEvent::Moved(_) | WindowEvent::ThemeChanged(_) - | WindowEvent::TouchpadPressure { .. } => EventResponse { + | WindowEvent::TouchpadPressure { .. } + | WindowEvent::CloseRequested => EventResponse { repaint: true, consumed: false, }, From 3e55b1e3eac1eb1375b823ff9823b9c9389be8e1 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Tue, 28 Nov 2023 10:43:39 +0100 Subject: [PATCH 11/46] Update links in docs --- crates/eframe/src/epi.rs | 2 +- crates/eframe/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/eframe/src/epi.rs b/crates/eframe/src/epi.rs index 982eb54814d..90da4824129 100644 --- a/crates/eframe/src/epi.rs +++ b/crates/eframe/src/epi.rs @@ -298,7 +298,7 @@ pub struct NativeOptions { /// /// This feature was introduced in . /// - /// When `true`, [`winit::platform::run_return::EventLoopExtRunReturn::run_return`] is used. + /// When `true`, [`winit::platform::run_on_demand::EventLoopExtRunOnDemand`] is used. /// When `false`, [`winit::event_loop::EventLoop::run`] is used. pub run_and_return: bool, diff --git a/crates/eframe/src/lib.rs b/crates/eframe/src/lib.rs index ff30cf283e3..06df34fc3d2 100644 --- a/crates/eframe/src/lib.rs +++ b/crates/eframe/src/lib.rs @@ -316,7 +316,7 @@ pub enum Error { #[error("winit error: {0}")] Winit(#[from] winit::error::OsError), - /// An error from [`winit::EventLoop`]. + /// An error from [`winit::event_loop::EventLoop`]. #[cfg(not(target_arch = "wasm32"))] #[error("winit EventLoopError: {0}")] WinitEventLoop(#[from] winit::error::EventLoopError), From 8c8f2f66a2a88de297bc59791a3402b24c310009 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 10:52:45 +0100 Subject: [PATCH 12/46] Update to cocoa 0.25.0 --- Cargo.lock | 88 +++++++--------------------------------- crates/eframe/Cargo.toml | 2 +- 2 files changed, 15 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f5d27e6127..8f9ea46a2d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,9 +193,9 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arboard" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac57f2b058a76363e357c056e4f74f1945bf734d37b8b3ef49066c4787dde0fc" +checksum = "aafb29b107435aa276664c1db8954ac27a6e105cdad3c88287a199eb0e313c08" dependencies = [ "clipboard-win", "log", @@ -205,7 +205,7 @@ dependencies = [ "parking_lot", "thiserror", "winapi", - "x11rb 0.10.1", + "x11rb", ] [[package]] @@ -807,16 +807,16 @@ dependencies = [ [[package]] name = "cocoa" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", "core-foundation", - "core-graphics 0.22.3", - "foreign-types 0.3.2", + "core-graphics", + "foreign-types", "libc", "objc", ] @@ -906,19 +906,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types 0.3.2", - "libc", -] - [[package]] name = "core-graphics" version = "0.23.1" @@ -928,7 +915,7 @@ dependencies = [ "bitflags 1.3.2", "core-foundation", "core-graphics-types", - "foreign-types 0.5.0", + "foreign-types", "libc", ] @@ -1588,15 +1575,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared 0.1.1", -] - [[package]] name = "foreign-types" version = "0.5.0" @@ -1604,7 +1582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared 0.3.1", + "foreign-types-shared", ] [[package]] @@ -1618,12 +1596,6 @@ dependencies = [ "syn 2.0.37", ] -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -1734,16 +1706,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "gethostname" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "gethostname" version = "0.3.0" @@ -2456,7 +2418,7 @@ dependencies = [ "bitflags 2.4.0", "block", "core-graphics-types", - "foreign-types 0.5.0", + "foreign-types", "log", "objc", "paste", @@ -4768,7 +4730,7 @@ dependencies = [ "calloop", "cfg_aliases", "core-foundation", - "core-graphics 0.23.1", + "core-graphics", "cursor-icon", "icrate", "js-sys", @@ -4799,7 +4761,7 @@ dependencies = [ "web-time", "windows-sys 0.48.0", "x11-dl", - "x11rb 0.12.0", + "x11rb", "xkbcommon-dl", ] @@ -4823,19 +4785,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "x11rb" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" -dependencies = [ - "gethostname 0.2.3", - "nix 0.24.3", - "winapi", - "winapi-wsapoll", - "x11rb-protocol 0.10.0", -] - [[package]] name = "x11rb" version = "0.12.0" @@ -4843,23 +4792,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" dependencies = [ "as-raw-xcb-connection", - "gethostname 0.3.0", + "gethostname", "libc", "libloading 0.7.4", "nix 0.26.4", "once_cell", "winapi", "winapi-wsapoll", - "x11rb-protocol 0.12.0", -] - -[[package]] -name = "x11rb-protocol" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67" -dependencies = [ - "nix 0.24.3", + "x11rb-protocol", ] [[package]] diff --git a/crates/eframe/Cargo.toml b/crates/eframe/Cargo.toml index 5de1d7c88a9..2e5585540b4 100644 --- a/crates/eframe/Cargo.toml +++ b/crates/eframe/Cargo.toml @@ -149,7 +149,7 @@ wgpu = { workspace = true, optional = true } # mac: [target.'cfg(any(target_os = "macos"))'.dependencies] -cocoa = "0.24.1" # Stuck on old version until we update to winit 0.29 +cocoa = "0.25.0" objc = "0.2.7" # windows: From 3dc23de3a5c23bef599d0b134ef49e80ed458fba Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 10:53:43 +0100 Subject: [PATCH 13/46] Update to smithay-clipboard 0.7.0 --- Cargo.lock | 200 +++++++---------------------------- crates/egui-winit/Cargo.toml | 2 +- 2 files changed, 41 insertions(+), 161 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f9ea46a2d1..bddae4c73ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -670,7 +670,7 @@ dependencies = [ "calloop", "rustix 0.38.21", "wayland-backend", - "wayland-client 0.31.1", + "wayland-client", ] [[package]] @@ -1314,7 +1314,7 @@ dependencies = [ "glutin", "glutin-winit", "log", - "memoffset 0.7.1", + "memoffset", "puffin", "raw-window-handle 0.5.2", "wasm-bindgen", @@ -1812,7 +1812,7 @@ dependencies = [ "objc2 0.4.1", "once_cell", "raw-window-handle 0.5.2", - "wayland-sys 0.31.1", + "wayland-sys", "windows-sys 0.48.0", "x11-dl", ] @@ -2279,9 +2279,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.148" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" @@ -2373,15 +2373,6 @@ version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - [[package]] name = "memmap2" version = "0.9.0" @@ -2391,15 +2382,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.7.1" @@ -2530,18 +2512,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.6.5", -] - [[package]] name = "nix" version = "0.26.4" @@ -2551,7 +2521,7 @@ dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "memoffset 0.7.1", + "memoffset", ] [[package]] @@ -3360,8 +3330,8 @@ checksum = "1729a30a469de249c6effc17ec8d039b0aa29b3af79b819b7f51cb6ab8046a90" dependencies = [ "ab_glyph", "log", - "memmap2 0.9.0", - "smithay-client-toolkit 0.18.0", + "memmap2", + "smithay-client-toolkit", "tiny-skia 0.11.2", ] @@ -3489,24 +3459,6 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" -[[package]] -name = "smithay-client-toolkit" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870427e30b8f2cbe64bf43ec4b86e88fe39b0a84b3f15efd9c9c2d020bc86eb9" -dependencies = [ - "bitflags 1.3.2", - "dlib", - "lazy_static", - "log", - "memmap2 0.5.10", - "nix 0.24.3", - "pkg-config", - "wayland-client 0.29.5", - "wayland-cursor 0.29.5", - "wayland-protocols 0.29.5", -] - [[package]] name = "smithay-client-toolkit" version = "0.18.0" @@ -3519,27 +3471,28 @@ dependencies = [ "cursor-icon", "libc", "log", - "memmap2 0.9.0", + "memmap2", "rustix 0.38.21", "thiserror", "wayland-backend", - "wayland-client 0.31.1", + "wayland-client", "wayland-csd-frame", - "wayland-cursor 0.31.0", - "wayland-protocols 0.31.0", + "wayland-cursor", + "wayland-protocols", "wayland-protocols-wlr", - "wayland-scanner 0.31.0", + "wayland-scanner", "xkeysym", ] [[package]] name = "smithay-clipboard" -version = "0.6.6" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8" +checksum = "0bb62b280ce5a5cba847669933a0948d00904cf83845c944eae96a4738cea1a6" dependencies = [ - "smithay-client-toolkit 0.16.1", - "wayland-client 0.29.5", + "libc", + "smithay-client-toolkit", + "wayland-backend", ] [[package]] @@ -4157,26 +4110,10 @@ checksum = "19152ddd73f45f024ed4534d9ca2594e0ef252c1847695255dae47f34df9fbe4" dependencies = [ "cc", "downcast-rs", - "nix 0.26.4", + "nix", "scoped-tls", "smallvec", - "wayland-sys 0.31.1", -] - -[[package]] -name = "wayland-client" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" -dependencies = [ - "bitflags 1.3.2", - "downcast-rs", - "libc", - "nix 0.24.3", - "scoped-tls", - "wayland-commons", - "wayland-scanner 0.29.5", - "wayland-sys 0.29.5", + "wayland-sys", ] [[package]] @@ -4186,21 +4123,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ca7d52347346f5473bf2f56705f360e8440873052e575e55890c4fa57843ed3" dependencies = [ "bitflags 2.4.0", - "nix 0.26.4", + "nix", "wayland-backend", - "wayland-scanner 0.31.0", -] - -[[package]] -name = "wayland-commons" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" -dependencies = [ - "nix 0.24.3", - "once_cell", - "smallvec", - "wayland-sys 0.29.5", + "wayland-scanner", ] [[package]] @@ -4214,40 +4139,17 @@ dependencies = [ "wayland-backend", ] -[[package]] -name = "wayland-cursor" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" -dependencies = [ - "nix 0.24.3", - "wayland-client 0.29.5", - "xcursor", -] - [[package]] name = "wayland-cursor" version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44aa20ae986659d6c77d64d808a046996a932aa763913864dc40c359ef7ad5b" dependencies = [ - "nix 0.26.4", - "wayland-client 0.31.1", + "nix", + "wayland-client", "xcursor", ] -[[package]] -name = "wayland-protocols" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" -dependencies = [ - "bitflags 1.3.2", - "wayland-client 0.29.5", - "wayland-commons", - "wayland-scanner 0.29.5", -] - [[package]] name = "wayland-protocols" version = "0.31.0" @@ -4256,8 +4158,8 @@ checksum = "e253d7107ba913923dc253967f35e8561a3c65f914543e46843c88ddd729e21c" dependencies = [ "bitflags 2.4.0", "wayland-backend", - "wayland-client 0.31.1", - "wayland-scanner 0.31.0", + "wayland-client", + "wayland-scanner", ] [[package]] @@ -4268,9 +4170,9 @@ checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" dependencies = [ "bitflags 2.4.0", "wayland-backend", - "wayland-client 0.31.1", - "wayland-protocols 0.31.0", - "wayland-scanner 0.31.0", + "wayland-client", + "wayland-protocols", + "wayland-scanner", ] [[package]] @@ -4281,20 +4183,9 @@ checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ "bitflags 2.4.0", "wayland-backend", - "wayland-client 0.31.1", - "wayland-protocols 0.31.0", - "wayland-scanner 0.31.0", -] - -[[package]] -name = "wayland-scanner" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", + "wayland-client", + "wayland-protocols", + "wayland-scanner", ] [[package]] @@ -4308,17 +4199,6 @@ dependencies = [ "quote", ] -[[package]] -name = "wayland-sys" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" -dependencies = [ - "dlib", - "lazy_static", - "pkg-config", -] - [[package]] name = "wayland-sys" version = "0.31.1" @@ -4736,7 +4616,7 @@ dependencies = [ "js-sys", "libc", "log", - "memmap2 0.9.0", + "memmap2", "ndk", "ndk-sys", "objc2 0.4.1", @@ -4748,14 +4628,14 @@ dependencies = [ "redox_syscall 0.3.5", "rustix 0.38.21", "sctk-adwaita", - "smithay-client-toolkit 0.18.0", + "smithay-client-toolkit", "smol_str", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", "wayland-backend", - "wayland-client 0.31.1", - "wayland-protocols 0.31.0", + "wayland-client", + "wayland-protocols", "wayland-protocols-plasma", "web-sys", "web-time", @@ -4795,7 +4675,7 @@ dependencies = [ "gethostname", "libc", "libloading 0.7.4", - "nix 0.26.4", + "nix", "once_cell", "winapi", "winapi-wsapoll", @@ -4808,7 +4688,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" dependencies = [ - "nix 0.26.4", + "nix", ] [[package]] @@ -4826,7 +4706,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" dependencies = [ - "nix 0.26.4", + "nix", "winapi", ] @@ -4894,7 +4774,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix 0.26.4", + "nix", "once_cell", "ordered-stream", "rand", diff --git a/crates/egui-winit/Cargo.toml b/crates/egui-winit/Cargo.toml index 6fa007da896..f4486740fee 100644 --- a/crates/egui-winit/Cargo.toml +++ b/crates/egui-winit/Cargo.toml @@ -76,7 +76,7 @@ serde = { version = "1.0", optional = true, features = ["derive"] } webbrowser = { version = "0.8.3", optional = true } [target.'cfg(any(target_os="linux", target_os="dragonfly", target_os="freebsd", target_os="netbsd", target_os="openbsd"))'.dependencies] -smithay-clipboard = { version = "0.6.3", optional = true } +smithay-clipboard = { version = "0.7.0", optional = true } [target.'cfg(not(target_os = "android"))'.dependencies] arboard = { version = "3.2", optional = true, default-features = false } From 0d822c97d1e552ca42b47d457b201687cab61db0 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 10:54:41 +0100 Subject: [PATCH 14/46] Updating plist v1.5.0 -> v1.5.1 --- Cargo.lock | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bddae4c73ec..a516d6244ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2823,14 +2823,14 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "plist" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdc0001cfea3db57a2e24bc0d818e9e20e554b5f97fabb9bc231dc240269ae06" +checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa" dependencies = [ "base64 0.21.4", "indexmap 1.9.3", "line-wrap", - "quick-xml 0.29.0", + "quick-xml", "serde", "time", ] @@ -2969,15 +2969,6 @@ dependencies = [ "puffin_http", ] -[[package]] -name = "quick-xml" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51" -dependencies = [ - "memchr", -] - [[package]] name = "quick-xml" version = "0.30.0" @@ -4195,7 +4186,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb8e28403665c9f9513202b7e1ed71ec56fde5c107816843fb14057910b2c09c" dependencies = [ "proc-macro2", - "quick-xml 0.30.0", + "quick-xml", "quote", ] From 7c89b675f24f93b1e258512fb79e2ca2e286ceef Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 11:05:32 +0100 Subject: [PATCH 15/46] Simplify egui_extras dependency list for the svg feature --- Cargo.lock | 2 -- crates/egui_extras/Cargo.toml | 4 +--- crates/egui_extras/src/image.rs | 2 ++ crates/egui_extras/src/loaders/svg_loader.rs | 5 ++++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a516d6244ab..f9151f10ec0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1298,8 +1298,6 @@ dependencies = [ "resvg", "serde", "syntect", - "tiny-skia 0.8.4", - "usvg", ] [[package]] diff --git a/crates/egui_extras/Cargo.toml b/crates/egui_extras/Cargo.toml index 26f1901341d..d48549b79f3 100644 --- a/crates/egui_extras/Cargo.toml +++ b/crates/egui_extras/Cargo.toml @@ -53,7 +53,7 @@ image = ["dep:image"] puffin = ["dep:puffin", "egui/puffin"] ## Support loading svg images. -svg = ["resvg", "tiny-skia", "usvg"] +svg = ["resvg"] ## Enable better syntax highlighting using [`syntect`](https://docs.rs/syntect). syntect = ["dep:syntect"] @@ -93,8 +93,6 @@ syntect = { version = "5", optional = true, default-features = false, features = # svg feature resvg = { version = "0.28", optional = true, default-features = false } -tiny-skia = { version = "0.8", optional = true, default-features = false } # must be updated in lock-step with resvg -usvg = { version = "0.28", optional = true, default-features = false } # http feature ehttp = { version = "0.3.1", optional = true, default-features = false } diff --git a/crates/egui_extras/src/image.rs b/crates/egui_extras/src/image.rs index 1ad3cea6c7e..8426a546fe4 100644 --- a/crates/egui_extras/src/image.rs +++ b/crates/egui_extras/src/image.rs @@ -2,6 +2,8 @@ use egui::{mutex::Mutex, TextureFilter, TextureOptions}; +use resvg::{tiny_skia, usvg}; + #[cfg(feature = "svg")] pub use usvg::FitTo; diff --git a/crates/egui_extras/src/loaders/svg_loader.rs b/crates/egui_extras/src/loaders/svg_loader.rs index ff2cab86844..00a3bdfef89 100644 --- a/crates/egui_extras/src/loaders/svg_loader.rs +++ b/crates/egui_extras/src/loaders/svg_loader.rs @@ -1,10 +1,13 @@ +use std::{mem::size_of, path::Path, sync::Arc}; + use egui::{ ahash::HashMap, load::{BytesPoll, ImageLoadResult, ImageLoader, ImagePoll, LoadError, SizeHint}, mutex::Mutex, ColorImage, }; -use std::{mem::size_of, path::Path, sync::Arc}; + +use resvg::usvg; type Entry = Result, String>; From 0dbd597de0e4ea37843328968dfa8c205857cbde Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 11:11:28 +0100 Subject: [PATCH 16/46] Update deny.toml --- deny.toml | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/deny.toml b/deny.toml index 4536cd3f9f0..e0ce6331b19 100644 --- a/deny.toml +++ b/deny.toml @@ -34,27 +34,24 @@ deny = [ ] skip = [ - { name = "arrayvec" }, # old version via tiny-skiaz - { name = "base64" }, # small crate, old version from usvg - { name = "glow" }, # TODO(@wumpf): Old version use for glow backend right now, newer for wgpu. Updating this trickles out to updating winit. - { name = "glutin_wgl_sys" }, # TODO(@wumpf): Old version use for glow backend right now, newer for wgpu. Updating this trickles out to updating winit. - { name = "libloading" }, # wgpu-hal itself depends on 0.8 while some of its dependencies, like ash and d3d12, depend on 0.7 - { name = "memoffset" }, # tiny dependency - { name = "nix" }, # old version via winit - { name = "redox_syscall" }, # old version via winit - { name = "spin" }, # old version via ring through rusttls and other libraries, newer for wgpu. - { name = "time" }, # old version pulled in by unmaintianed crate 'chrono' - { name = "tiny-skia" }, # winit uses a different version from egui_extras (TODO(emilk): update egui_extras!) - { name = "ttf-parser" }, # different versions pulled in by ab_glyph and usvg - { name = "wayland-sys" }, # old version via winit - { name = "windows_x86_64_msvc" }, # old version via glutin - { name = "windows-sys" }, # old version via glutin - { name = "windows" }, # old version via accesskit + { name = "arrayvec" }, # old version via tiny-skiaz + { name = "base64" }, # small crate, old version from usvg + { name = "glow" }, # TODO(@wumpf): Old version use for glow backend right now, newer for wgpu. Updating this trickles out to updating winit. + { name = "glutin_wgl_sys" }, # TODO(@wumpf): Old version use for glow backend right now, newer for wgpu. Updating this trickles out to updating winit. + { name = "libloading" }, # wgpu-hal itself depends on 0.8 while some of its dependencies, like ash and d3d12, depend on 0.7 + { name = "memoffset" }, # tiny dependency + { name = "redox_syscall" }, # old version via directories-next + { name = "spin" }, # old version via ring through rusttls and other libraries, newer for wgpu. + { name = "time" }, # old version pulled in by unmaintianed crate 'chrono' + { name = "ttf-parser" }, # different versions pulled in by ab_glyph and usvg + { name = "windows" }, # old version via accesskit_windows ] skip-tree = [ { name = "criterion" }, # dev-dependency { name = "foreign-types" }, # small crate. Old version via cocoa and core-graphics (winit). + { name = "objc2" }, # old version via accesskit_macos { name = "rfd" }, # example dependency + { name = "tiny-skia" }, # old version via old resvg in egui_extras - see https://github.com/emilk/egui/issues/3652 ] From b4e624679fa669ef2decf3ae3f01e45cd6bbd713 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 11:44:03 +0100 Subject: [PATCH 17/46] Fix svg-related build problem --- crates/egui_extras/src/image.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/egui_extras/src/image.rs b/crates/egui_extras/src/image.rs index 8426a546fe4..3aeb737b575 100644 --- a/crates/egui_extras/src/image.rs +++ b/crates/egui_extras/src/image.rs @@ -2,6 +2,7 @@ use egui::{mutex::Mutex, TextureFilter, TextureOptions}; +#[cfg(feature = "svg")] use resvg::{tiny_skia, usvg}; #[cfg(feature = "svg")] From bb5e077f00d9a7b059fb8a3b347a94d10117488b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 11:44:14 +0100 Subject: [PATCH 18/46] Return errors when creating event loop --- crates/eframe/src/native/run.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 82ed5c6473e..f95ec7b24cd 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -34,12 +34,12 @@ fn create_event_loop_builder( event_loop_builder } -fn create_event_loop(native_options: &mut epi::NativeOptions) -> EventLoop { +fn create_event_loop(native_options: &mut epi::NativeOptions) -> Result> { crate::profile_function!(); let mut builder = create_event_loop_builder(native_options); crate::profile_scope!("EventLoopBuilder::build"); - builder.build().unwrap() + Ok(builder.build()?) } /// Access a thread-local event loop. @@ -49,16 +49,20 @@ fn create_event_loop(native_options: &mut epi::NativeOptions) -> EventLoop( mut native_options: epi::NativeOptions, f: impl FnOnce(&mut EventLoop, epi::NativeOptions) -> R, -) -> R { +) -> Result { thread_local!(static EVENT_LOOP: RefCell>> = RefCell::new(None)); EVENT_LOOP.with(|event_loop| { // Since we want to reference NativeOptions when creating the EventLoop we can't // do that as part of the lazy thread local storage initialization and so we instead // create the event loop lazily here - let mut event_loop = event_loop.borrow_mut(); - let event_loop = event_loop.get_or_insert_with(|| create_event_loop(&mut native_options)); - f(event_loop, native_options) + let mut event_loop_lock = event_loop.borrow_mut(); + let event_loop = if let Some(event_loop) = &mut *event_loop_lock { + event_loop + } else { + event_loop_lock.insert(create_event_loop(&mut native_options)?) + }; + Ok(f(event_loop, native_options)) }) } @@ -389,10 +393,10 @@ pub fn run_glow( return with_event_loop(native_options, |event_loop, native_options| { let glow_eframe = GlowWinitApp::new(event_loop, app_name, native_options, app_creator); run_and_return(event_loop, glow_eframe) - }); + })?; } - let event_loop = create_event_loop(&mut native_options); + let event_loop = create_event_loop(&mut native_options)?; let glow_eframe = GlowWinitApp::new(&event_loop, app_name, native_options, app_creator); run_and_exit(event_loop, glow_eframe) } @@ -412,10 +416,10 @@ pub fn run_wgpu( return with_event_loop(native_options, |event_loop, native_options| { let wgpu_eframe = WgpuWinitApp::new(event_loop, app_name, native_options, app_creator); run_and_return(event_loop, wgpu_eframe) - }); + })?; } - let event_loop = create_event_loop(&mut native_options); + let event_loop = create_event_loop(&mut native_options)?; let wgpu_eframe = WgpuWinitApp::new(&event_loop, app_name, native_options, app_creator); run_and_exit(event_loop, wgpu_eframe) } From fefa5afdd91f49f6f368bac992288cfe6e729de3 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 11:45:22 +0100 Subject: [PATCH 19/46] Move warning comment --- crates/eframe/src/native/glow_integration.rs | 7 +++++++ crates/eframe/src/native/run.rs | 7 ------- crates/eframe/src/native/wgpu_integration.rs | 7 +++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index 95d1a44339f..cf7c0b7d387 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -1,3 +1,10 @@ +//! Note that this file contains code very similar to [`wgpu_integration`]. +//! When making changes to one you often also want to apply it to the other. +//! +//! This is also very complex code, and not very pretty. +//! There is a bunch of improvements we could do, +//! like removing a bunch of `unwraps`. + use std::{cell::RefCell, rc::Rc, sync::Arc, time::Instant}; use glutin::{ diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index f95ec7b24cd..14a321d11e8 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -1,10 +1,3 @@ -//! Note that this file contains two similar paths - one for [`glow`], one for [`wgpu`]. -//! When making changes to one you often also want to apply it to the other. -//! -//! This is also very complex code, and not very pretty. -//! There is a bunch of improvements we could do, -//! like removing a bunch of `unwraps`. - use std::{cell::RefCell, time::Instant}; use winit::event_loop::{EventLoop, EventLoopBuilder}; diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index 473d5b8ecd5..e52d9e2fc0c 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -1,3 +1,10 @@ +//! Note that this file contains code very similar to [`glow_integration`]. +//! When making changes to one you often also want to apply it to the other. +//! +//! This is also very complex code, and not very pretty. +//! There is a bunch of improvements we could do, +//! like removing a bunch of `unwraps`. + use std::{cell::RefCell, rc::Rc, sync::Arc, time::Instant}; use parking_lot::Mutex; From 1df781d708e0956d83b66ff03f41699f96816523 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 11:52:35 +0100 Subject: [PATCH 20/46] Remove noop responses to ScaleFactorChanged --- crates/eframe/src/native/glow_integration.rs | 6 ------ crates/eframe/src/native/wgpu_integration.rs | 3 --- 2 files changed, 9 deletions(-) diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index cf7c0b7d387..475cdb13f56 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -703,12 +703,6 @@ impl GlowWinitRunning { } } - winit::event::WindowEvent::ScaleFactorChanged { .. } => { - if viewport_id.is_some() { - repaint_asap = true; - } - } - winit::event::WindowEvent::CloseRequested => { if viewport_id == Some(ViewportId::ROOT) && self.integration.should_close() { log::debug!( diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index e52d9e2fc0c..ffd6c4ffba4 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -710,9 +710,6 @@ impl WgpuWinitRunning { } } - winit::event::WindowEvent::ScaleFactorChanged { .. } => { - repaint_asap = true; - } winit::event::WindowEvent::CloseRequested => { if viewport_id == Some(ViewportId::ROOT) && integration.should_close() { log::debug!( From 6b714a7965294697ec2cacbc617999e9500292db Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 11:53:19 +0100 Subject: [PATCH 21/46] Remove `Prefence` typo exception --- .typos.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.typos.toml b/.typos.toml index 46d137138ea..6d856495178 100644 --- a/.typos.toml +++ b/.typos.toml @@ -3,8 +3,7 @@ # run: typos [default.extend-words] -nknown = "nknown" # part of @55nknown username -Prefence = "Prefence" # typo in glutin_winit API +nknown = "nknown" # part of @55nknown username [files] extend-exclude = ["web_demo/egui_demo_app.js"] # auto-generated From 87870b3b38e0afb5f33cfcd5f674476b5e76c72b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 11:58:05 +0100 Subject: [PATCH 22/46] Rename `ViewportCommand::IMEPosition` to `IMERect` --- crates/egui-winit/src/lib.rs | 9 ++++++--- crates/egui/src/viewport.rs | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 406a84fed5a..354f564f324 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -1176,10 +1176,13 @@ fn process_viewport_command( .expect("Invalid ICON data!") })); } - ViewportCommand::IMEPosition(pos) => { + ViewportCommand::IMERect(rect) => { window.set_ime_cursor_area( - PhysicalPosition::new(pixels_per_point * pos.x, pixels_per_point * pos.y), - PhysicalSize::new(100, 100), + PhysicalPosition::new(pixels_per_point * rect.min.x, pixels_per_point * rect.min.y), + PhysicalSize::new( + pixels_per_point * rect.size().x, + pixels_per_point * rect.size().y, + ), ); } ViewportCommand::IMEAllowed(v) => window.set_ime_allowed(v), diff --git a/crates/egui/src/viewport.rs b/crates/egui/src/viewport.rs index 45d2e535324..0d66121ece7 100644 --- a/crates/egui/src/viewport.rs +++ b/crates/egui/src/viewport.rs @@ -897,7 +897,8 @@ pub enum ViewportCommand { /// The the window icon. Icon(Option>), - IMEPosition(Pos2), + /// Set the IME cursor editing area. + IMERect(crate::Rect), IMEAllowed(bool), IMEPurpose(IMEPurpose), From fca36901da304db7a622ac6080b2d95a6cff1705 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 12:04:08 +0100 Subject: [PATCH 23/46] Log result of request_inner_size --- crates/egui-winit/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 354f564f324..7ab36c9c643 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -1092,7 +1092,12 @@ fn process_viewport_command( ViewportCommand::InnerSize(size) => { let width_px = pixels_per_point * size.x.max(1.0); let height_px = pixels_per_point * size.y.max(1.0); - let _ = window.request_inner_size(PhysicalSize::new(width_px, height_px)); + if window + .request_inner_size(PhysicalSize::new(width_px, height_px)) + .is_some() + { + log::debug!("ViewportCommand::InnerSize ignored by winit"); + } } ViewportCommand::BeginResize(direction) => { if let Err(err) = window.drag_resize_window(match direction { From b5fcda10f8b3cb2af028b033de0b6c00ee3805a3 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 12:36:10 +0100 Subject: [PATCH 24/46] Fix event loop and improve trace logging --- crates/eframe/src/native/glow_integration.rs | 4 + crates/eframe/src/native/run.rs | 118 ++++++++---------- crates/eframe/src/native/winit_integration.rs | 4 +- crates/egui_demo_app/src/main.rs | 2 + 4 files changed, 62 insertions(+), 66 deletions(-) diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index 475cdb13f56..d6893fd867f 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -745,7 +745,11 @@ impl GlowWinitRunning { event_response = self .integration .on_window_event(event, viewport.egui_winit.as_mut().unwrap()); + } else { + log::trace!("Ignoring event: no viewport for {viewport_id:?}"); } + } else { + log::trace!("Ignoring event: no viewport_id"); } if event_response.repaint { diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 14a321d11e8..48b5d762a08 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -66,7 +66,7 @@ fn run_and_return( ) -> Result<()> { use winit::{event_loop::ControlFlow, platform::run_on_demand::EventLoopExtRunOnDemand}; - log::debug!("Entering the winit event loop (run_return)…"); + log::debug!("Entering the winit event loop (run_on_demand)…"); // When to repaint what window let mut windows_next_repaint_times = HashMap::default(); @@ -76,6 +76,12 @@ fn run_and_return( event_loop.run_on_demand(|event, event_loop_window_target| { crate::profile_scope!("winit_event", short_event_description(&event)); + log::trace!("winit event: {event:?}"); + + if matches!(event, winit::event::Event::AboutToWait) { + return; // early-out: don't trigger another wait + } + let event_result = match &event { winit::event::Event::LoopExiting => { // On Mac, Cmd-Q we get here and then `run_on_demand` doesn't return (despite its name), @@ -120,7 +126,10 @@ fn run_and_return( } event => match winit_app.on_event(event_loop_window_target, event) { - Ok(event_result) => event_result, + Ok(event_result) => { + log::trace!("event_result: {event_result:?}"); + event_result + } Err(err) => { log::error!("Exiting because of error: {err} during event {event:?}"); returned_result = Err(err); @@ -134,7 +143,7 @@ fn run_and_return( event_loop_window_target.set_control_flow(ControlFlow::Wait); } EventResult::RepaintNow(window_id) => { - log::trace!("Repaint caused by {}", short_event_description(&event)); + log::trace!("RepaintNow caused by {}", short_event_description(&event)); if cfg!(target_os = "windows") { // Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 windows_next_repaint_times.remove(&window_id); @@ -146,6 +155,7 @@ fn run_and_return( } } EventResult::RepaintNext(window_id) => { + log::trace!("RepaintNext caused by {}", short_event_description(&event)); windows_next_repaint_times.insert(window_id, Instant::now()); } EventResult::RepaintAt(window_id, repaint_time) => { @@ -166,38 +176,25 @@ fn run_and_return( let mut next_repaint_time = windows_next_repaint_times.values().min().copied(); - // This is for not duplicating redraw requests - use winit::event::Event; - if matches!( - event, - Event::WindowEvent { - event: winit::event::WindowEvent::RedrawRequested, - .. - } | Event::Resumed - ) { - windows_next_repaint_times.retain(|window_id, repaint_time| { - if Instant::now() < *repaint_time { - return true; - }; + windows_next_repaint_times.retain(|window_id, repaint_time| { + if Instant::now() < *repaint_time { + return true; // not yet ready + }; - next_repaint_time = None; - event_loop_window_target.set_control_flow(ControlFlow::Poll); + next_repaint_time = None; + event_loop_window_target.set_control_flow(ControlFlow::Poll); - if let Some(window) = winit_app.window(*window_id) { - log::trace!("request_redraw for {window_id:?}"); - window.request_redraw(); - true - } else { - false - } - }); - } + if let Some(window) = winit_app.window(*window_id) { + log::trace!("request_redraw for {window_id:?}"); + window.request_redraw(); + true + } else { + log::trace!("No window found for {window_id:?}"); + false + } + }); if let Some(next_repaint_time) = next_repaint_time { - let time_until_next = next_repaint_time.saturating_duration_since(Instant::now()); - if time_until_next < std::time::Duration::from_secs(10_000) { - log::trace!("WaitUntil {time_until_next:?}"); - } event_loop_window_target.set_control_flow(ControlFlow::WaitUntil(next_repaint_time)); }; })?; @@ -235,6 +232,12 @@ fn run_and_exit( .run(move |event, event_loop_window_target| { crate::profile_scope!("winit_event", short_event_description(&event)); + log::trace!("winit event: {event:?}"); + + if matches!(event, winit::event::Event::AboutToWait) { + return; // early-out: don't trigger another wait + } + let event_result = match &event { winit::event::Event::LoopExiting => { log::debug!("Received Event::LoopExiting"); @@ -276,7 +279,10 @@ fn run_and_exit( } event => match winit_app.on_event(event_loop_window_target, event) { - Ok(event_result) => event_result, + Ok(event_result) => { + log::trace!("event_result: {event_result:?}"); + event_result + } Err(err) => { panic!("eframe encountered a fatal error: {err} during event {event:?}"); } @@ -288,7 +294,7 @@ fn run_and_exit( event_loop_window_target.set_control_flow(ControlFlow::Wait); } EventResult::RepaintNow(window_id) => { - log::trace!("Repaint caused by {}", short_event_description(&event)); + log::trace!("RepaintNow caused by {}", short_event_description(&event)); if cfg!(target_os = "windows") { // Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 windows_next_repaint_times.remove(&window_id); @@ -300,7 +306,7 @@ fn run_and_exit( } } EventResult::RepaintNext(window_id) => { - log::trace!("Repaint caused by {}", short_event_description(&event)); + log::trace!("RepaintNext caused by {}", short_event_description(&event)); windows_next_repaint_times.insert(window_id, Instant::now()); } EventResult::RepaintAt(window_id, repaint_time) => { @@ -321,39 +327,25 @@ fn run_and_exit( let mut next_repaint_time = windows_next_repaint_times.values().min().copied(); - // This is for not duplicating redraw requests - use winit::event::Event; - if matches!( - event, - Event::WindowEvent { - event: winit::event::WindowEvent::RedrawRequested, - .. - } | Event::Resumed - ) { - windows_next_repaint_times.retain(|window_id, repaint_time| { - if Instant::now() < *repaint_time { - return true; - } - - next_repaint_time = None; - event_loop_window_target.set_control_flow(ControlFlow::Poll); + windows_next_repaint_times.retain(|window_id, repaint_time| { + if Instant::now() < *repaint_time { + return true; // not yet ready + } - if let Some(window) = winit_app.window(*window_id) { - log::trace!("request_redraw for {window_id:?}"); - window.request_redraw(); - true - } else { - false - } - }); - } + next_repaint_time = None; + event_loop_window_target.set_control_flow(ControlFlow::Poll); - if let Some(next_repaint_time) = next_repaint_time { - let time_until_next = next_repaint_time.saturating_duration_since(Instant::now()); - if time_until_next < std::time::Duration::from_secs(10_000) { - log::trace!("WaitUntil {time_until_next:?}"); + if let Some(window) = winit_app.window(*window_id) { + log::trace!("request_redraw for {window_id:?}"); + window.request_redraw(); + true + } else { + log::trace!("No window found for {window_id:?}"); + false } + }); + if let Some(next_repaint_time) = next_repaint_time { // WaitUntil seems to not work on iOS #[cfg(target_os = "ios")] winit_app diff --git a/crates/eframe/src/native/winit_integration.rs b/crates/eframe/src/native/winit_integration.rs index 6a2a97b32de..fc4910b4c64 100644 --- a/crates/eframe/src/native/winit_integration.rs +++ b/crates/eframe/src/native/winit_integration.rs @@ -118,10 +118,8 @@ pub fn system_theme(window: &Window, options: &crate::NativeOptions) -> Option) -> &'static str { - use winit::event::Event; - match event { - Event::UserEvent(user_event) => match user_event { + winit::event::Event::UserEvent(user_event) => match user_event { UserEvent::RequestRepaint { .. } => "UserEvent::RequestRepaint", #[cfg(feature = "accesskit")] UserEvent::AccessKitActionRequest(_) => "UserEvent::AccessKitActionRequest", diff --git a/crates/egui_demo_app/src/main.rs b/crates/egui_demo_app/src/main.rs index d81cedddb3b..8e564bef17e 100644 --- a/crates/egui_demo_app/src/main.rs +++ b/crates/egui_demo_app/src/main.rs @@ -41,6 +41,8 @@ fn main() -> Result<(), eframe::Error> { #[cfg(feature = "wgpu")] renderer: eframe::Renderer::Wgpu, + run_and_return: false, + ..Default::default() }; eframe::run_native( From 5914871ccbd443ccdb19a5e6a96c69ac773b174e Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 12:41:48 +0100 Subject: [PATCH 25/46] Code cleanup --- crates/eframe/src/native/run.rs | 230 ++++++++++++++++--------------- crates/egui_demo_app/src/main.rs | 2 - 2 files changed, 116 insertions(+), 116 deletions(-) diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 48b5d762a08..c6c0a860ef5 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -228,139 +228,141 @@ fn run_and_exit( // When to repaint what window let mut windows_next_repaint_times = HashMap::default(); - event_loop - .run(move |event, event_loop_window_target| { - crate::profile_scope!("winit_event", short_event_description(&event)); + event_loop.run(move |event, event_loop_window_target| { + crate::profile_scope!("winit_event", short_event_description(&event)); - log::trace!("winit event: {event:?}"); + log::trace!("winit event: {event:?}"); - if matches!(event, winit::event::Event::AboutToWait) { - return; // early-out: don't trigger another wait - } + if matches!(event, winit::event::Event::AboutToWait) { + return; // early-out: don't trigger another wait + } - let event_result = match &event { - winit::event::Event::LoopExiting => { - log::debug!("Received Event::LoopExiting"); - EventResult::Exit - } + let event_result = match &event { + winit::event::Event::LoopExiting => { + log::debug!("Received Event::LoopExiting"); + EventResult::Exit + } - winit::event::Event::WindowEvent { - event: winit::event::WindowEvent::RedrawRequested, - window_id, - } => { - windows_next_repaint_times.remove(window_id); - winit_app.run_ui_and_paint(*window_id) - } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + window_id, + } => { + windows_next_repaint_times.remove(window_id); + winit_app.run_ui_and_paint(*window_id) + } - winit::event::Event::UserEvent(UserEvent::RequestRepaint { - when, - frame_nr, - viewport_id, - }) => { - let current_frame_nr = winit_app.frame_nr(*viewport_id); - if current_frame_nr == *frame_nr || current_frame_nr == *frame_nr + 1 { - if let Some(window_id) = winit_app.window_id_from_viewport_id(*viewport_id) - { - EventResult::RepaintAt(window_id, *when) - } else { - EventResult::Wait - } + winit::event::Event::UserEvent(UserEvent::RequestRepaint { + when, + frame_nr, + viewport_id, + }) => { + let current_frame_nr = winit_app.frame_nr(*viewport_id); + if current_frame_nr == *frame_nr || current_frame_nr == *frame_nr + 1 { + if let Some(window_id) = winit_app.window_id_from_viewport_id(*viewport_id) { + EventResult::RepaintAt(window_id, *when) } else { - log::trace!("Got outdated UserEvent::RequestRepaint"); - EventResult::Wait // old request - we've already repainted + EventResult::Wait } + } else { + log::trace!("Got outdated UserEvent::RequestRepaint"); + EventResult::Wait // old request - we've already repainted } + } - winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached { - .. - }) => { - log::trace!("Woke up to check next_repaint_time"); - EventResult::Wait - } - - event => match winit_app.on_event(event_loop_window_target, event) { - Ok(event_result) => { - log::trace!("event_result: {event_result:?}"); - event_result - } - Err(err) => { - panic!("eframe encountered a fatal error: {err} during event {event:?}"); - } - }, - }; + winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached { + .. + }) => { + log::trace!("Woke up to check next_repaint_time"); + EventResult::Wait + } - match event_result { - EventResult::Wait => { - event_loop_window_target.set_control_flow(ControlFlow::Wait); + event => match winit_app.on_event(event_loop_window_target, event) { + Ok(event_result) => { + log::trace!("event_result: {event_result:?}"); + event_result } - EventResult::RepaintNow(window_id) => { - log::trace!("RepaintNow caused by {}", short_event_description(&event)); - if cfg!(target_os = "windows") { - // Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 - windows_next_repaint_times.remove(&window_id); - - winit_app.run_ui_and_paint(window_id); - } else { - // Fix for https://github.com/emilk/egui/issues/2425 - windows_next_repaint_times.insert(window_id, Instant::now()); - } + Err(err) => { + panic!("eframe encountered a fatal error: {err} during event {event:?}"); } - EventResult::RepaintNext(window_id) => { - log::trace!("RepaintNext caused by {}", short_event_description(&event)); + }, + }; + + match event_result { + EventResult::Wait => { + event_loop_window_target.set_control_flow(ControlFlow::Wait); + } + EventResult::RepaintNow(window_id) => { + log::trace!("RepaintNow caused by {}", short_event_description(&event)); + if cfg!(target_os = "windows") { + // Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 + windows_next_repaint_times.remove(&window_id); + + winit_app.run_ui_and_paint(window_id); + } else { + // Fix for https://github.com/emilk/egui/issues/2425 windows_next_repaint_times.insert(window_id, Instant::now()); } - EventResult::RepaintAt(window_id, repaint_time) => { - windows_next_repaint_times.insert( - window_id, - windows_next_repaint_times - .get(&window_id) - .map_or(repaint_time, |last| (*last).min(repaint_time)), - ); - } - EventResult::Exit => { - log::debug!("Quitting - saving app state…"); - winit_app.save_and_destroy(); - #[allow(clippy::exit)] - std::process::exit(0); - } } + EventResult::RepaintNext(window_id) => { + log::trace!("RepaintNext caused by {}", short_event_description(&event)); + windows_next_repaint_times.insert(window_id, Instant::now()); + } + EventResult::RepaintAt(window_id, repaint_time) => { + windows_next_repaint_times.insert( + window_id, + windows_next_repaint_times + .get(&window_id) + .map_or(repaint_time, |last| (*last).min(repaint_time)), + ); + } + EventResult::Exit => { + log::debug!("Quitting - saving app state…"); + winit_app.save_and_destroy(); + + log::debug!("Exiting with return code 0"); + #[allow(clippy::exit)] + std::process::exit(0); + } + } - let mut next_repaint_time = windows_next_repaint_times.values().min().copied(); + let mut next_repaint_time = windows_next_repaint_times.values().min().copied(); - windows_next_repaint_times.retain(|window_id, repaint_time| { - if Instant::now() < *repaint_time { - return true; // not yet ready - } + windows_next_repaint_times.retain(|window_id, repaint_time| { + if Instant::now() < *repaint_time { + return true; // not yet ready + } - next_repaint_time = None; - event_loop_window_target.set_control_flow(ControlFlow::Poll); + next_repaint_time = None; + event_loop_window_target.set_control_flow(ControlFlow::Poll); - if let Some(window) = winit_app.window(*window_id) { - log::trace!("request_redraw for {window_id:?}"); - window.request_redraw(); - true - } else { - log::trace!("No window found for {window_id:?}"); - false - } - }); - - if let Some(next_repaint_time) = next_repaint_time { - // WaitUntil seems to not work on iOS - #[cfg(target_os = "ios")] - winit_app - .get_window_winit_id(ViewportId::ROOT) - .map(|window_id| { - winit_app - .window(window_id) - .map(|window| window.request_redraw()) - }); - - event_loop_window_target - .set_control_flow(ControlFlow::WaitUntil(next_repaint_time)); - }; - }) - .map_err(|e| e.into()) + if let Some(window) = winit_app.window(*window_id) { + log::trace!("request_redraw for {window_id:?}"); + window.request_redraw(); + true + } else { + log::trace!("No window found for {window_id:?}"); + false + } + }); + + if let Some(next_repaint_time) = next_repaint_time { + // WaitUntil seems to not work on iOS + #[cfg(target_os = "ios")] + winit_app + .get_window_winit_id(ViewportId::ROOT) + .map(|window_id| { + winit_app + .window(window_id) + .map(|window| window.request_redraw()) + }); + + event_loop_window_target.set_control_flow(ControlFlow::WaitUntil(next_repaint_time)); + }; + })?; + + log::debug!("winit event loop unexpectedly returned"); + + Ok(()) } // ---------------------------------------------------------------------------- diff --git a/crates/egui_demo_app/src/main.rs b/crates/egui_demo_app/src/main.rs index 8e564bef17e..d81cedddb3b 100644 --- a/crates/egui_demo_app/src/main.rs +++ b/crates/egui_demo_app/src/main.rs @@ -41,8 +41,6 @@ fn main() -> Result<(), eframe::Error> { #[cfg(feature = "wgpu")] renderer: eframe::Renderer::Wgpu, - run_and_return: false, - ..Default::default() }; eframe::run_native( From d7c57d4a39537034b210264abfd43db9da9b6645 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 12:47:39 +0100 Subject: [PATCH 26/46] Clean up modifiers code --- crates/egui-winit/src/lib.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 7ab36c9c643..61500a15589 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -388,20 +388,22 @@ impl State { } WindowEvent::ModifiersChanged(state) => { use winit::keyboard::ModifiersKeyState::Pressed; - self.egui_input.modifiers.alt = - state.lalt_state() == Pressed || state.ralt_state() == Pressed; - self.egui_input.modifiers.ctrl = - state.lcontrol_state() == Pressed || state.rcontrol_state() == Pressed; - self.egui_input.modifiers.shift = - state.lshift_state() == Pressed || state.rshift_state() == Pressed; - self.egui_input.modifiers.mac_cmd = cfg!(target_os = "macos") - && (state.lsuper_state() == Pressed || state.rsuper_state() == Pressed); + let alt = state.lalt_state() == Pressed || state.ralt_state() == Pressed; + let ctrl = state.lcontrol_state() == Pressed || state.rcontrol_state() == Pressed; + let shift = state.lshift_state() == Pressed || state.rshift_state() == Pressed; + let super_ = state.lsuper_state() == Pressed || state.rsuper_state() == Pressed; + + self.egui_input.modifiers.alt = alt; + self.egui_input.modifiers.ctrl = ctrl; + self.egui_input.modifiers.shift = shift; + self.egui_input.modifiers.mac_cmd = cfg!(target_os = "macos") && super_; self.egui_input.modifiers.command = if cfg!(target_os = "macos") { - state.lsuper_state() == Pressed || state.rsuper_state() == Pressed + super_ } else { - state.lcontrol_state() == Pressed || state.rcontrol_state() == Pressed + ctrl }; + EventResponse { repaint: true, consumed: false, From 9b997a5957deca8054f3ae36b09e93e7a762fe0f Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 13:01:33 +0100 Subject: [PATCH 27/46] Fix IME output --- crates/eframe/src/web/app_runner.rs | 12 +++++----- crates/eframe/src/web/text_agent.rs | 8 ++++--- crates/egui-winit/src/lib.rs | 20 +++++++++------- crates/egui/src/data/output.rs | 25 ++++++++++++++++---- crates/egui/src/widgets/text_edit/builder.rs | 21 +++++----------- 5 files changed, 49 insertions(+), 37 deletions(-) diff --git a/crates/eframe/src/web/app_runner.rs b/crates/eframe/src/web/app_runner.rs index f5aab09a367..42cca65ed21 100644 --- a/crates/eframe/src/web/app_runner.rs +++ b/crates/eframe/src/web/app_runner.rs @@ -13,7 +13,7 @@ pub struct AppRunner { app: Box, pub(crate) needs_repaint: std::sync::Arc, last_save_time: f64, - pub(crate) text_cursor_pos: Option, + pub(crate) ime: Option, pub(crate) mutable_text_under_cursor: bool, // Output for the last run: @@ -112,7 +112,7 @@ impl AppRunner { app, needs_repaint, last_save_time: now_sec(), - text_cursor_pos: None, + ime: None, mutable_text_under_cursor: false, textures_delta: Default::default(), clipped_primitives: None, @@ -244,7 +244,7 @@ impl AppRunner { copied_text, events: _, // already handled mutable_text_under_cursor, - text_cursor_pos, + ime, #[cfg(feature = "accesskit")] accesskit_update: _, // not currently implemented } = platform_output; @@ -264,9 +264,9 @@ impl AppRunner { self.mutable_text_under_cursor = mutable_text_under_cursor; - if self.text_cursor_pos != text_cursor_pos { - super::text_agent::move_text_cursor(text_cursor_pos, self.canvas_id()); - self.text_cursor_pos = text_cursor_pos; + if self.ime != ime { + super::text_agent::move_text_cursor(ime, self.canvas_id()); + self.ime = ime; } } } diff --git a/crates/eframe/src/web/text_agent.rs b/crates/eframe/src/web/text_agent.rs index d4f3b5ca3c6..0bf8b532b7c 100644 --- a/crates/eframe/src/web/text_agent.rs +++ b/crates/eframe/src/web/text_agent.rs @@ -205,11 +205,13 @@ fn is_mobile() -> Option { // candidate window moves following text element (agent), // so it appears that the IME candidate window moves with text cursor. // On mobile devices, there is no need to do that. -pub fn move_text_cursor(cursor: Option, canvas_id: &str) -> Option<()> { +pub fn move_text_cursor(ime: Option, canvas_id: &str) -> Option<()> { let style = text_agent().style(); - // Note: movint agent on mobile devices will lead to unpredictable scroll. + // Note: moving agent on mobile devices will lead to unpredictable scroll. if is_mobile() == Some(false) { - cursor.as_ref().and_then(|&egui::Pos2 { x, y }| { + ime.as_ref().and_then(|ime| { + let egui::Pos2 { x, y } = ime.cursor_rect.left_top(); + let canvas = canvas_element(canvas_id)?; let bounding_rect = text_agent().get_bounding_client_rect(); let y = (y + (canvas.scroll_top() + canvas.offset_top()) as f32) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 61500a15589..3d4bb2b6a56 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -702,7 +702,7 @@ impl State { copied_text, events: _, // handled elsewhere mutable_text_under_cursor: _, // only used in eframe web - text_cursor_pos, + ime, #[cfg(feature = "accesskit")] accesskit_update, } = platform_output; @@ -719,19 +719,23 @@ impl State { self.clipboard.set(copied_text); } - let allow_ime = text_cursor_pos.is_some(); + let allow_ime = ime.is_some(); if self.allow_ime != allow_ime { self.allow_ime = allow_ime; window.set_ime_allowed(allow_ime); } - if let Some(egui::Pos2 { x, y }) = text_cursor_pos { + if let Some(ime) = ime { + let rect = ime.rect; + let pixels_per_point = self.pixels_per_point(); window.set_ime_cursor_area( - winit::dpi::LogicalPosition { x, y }, - winit::dpi::LogicalSize { - // TODO: What size to use? New size arg in winit 0.29 - width: 10, - height: 10, + winit::dpi::PhysicalPosition { + x: pixels_per_point * rect.min.x, + y: pixels_per_point * rect.min.y, + }, + winit::dpi::PhysicalSize { + width: pixels_per_point * rect.width(), + height: pixels_per_point * rect.height(), }, ); } diff --git a/crates/egui/src/data/output.rs b/crates/egui/src/data/output.rs index 6c5103b367c..70b3a30e13f 100644 --- a/crates/egui/src/data/output.rs +++ b/crates/egui/src/data/output.rs @@ -62,6 +62,21 @@ impl FullOutput { } } +/// Information about text beeing edited. +/// +/// Useful for IME. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub struct IMEOutput { + /// Where the [`crate::TextEdit`] is located on screen. + pub rect: crate::Rect, + + /// Where the cursor is. + /// + /// This is a very thin rectangle. + pub cursor_rect: crate::Rect, +} + /// The non-rendering part of what egui emits each frame. /// /// You can access (and modify) this with [`crate::Context::output`]. @@ -96,10 +111,10 @@ pub struct PlatformOutput { /// Use by `eframe` web to show/hide mobile keyboard and IME agent. pub mutable_text_under_cursor: bool, - /// Screen-space position of text edit cursor (used for IME). + /// This is et if, and only if, the user is currently editing text. /// - /// Iff `Some`, the user is editing text. - pub text_cursor_pos: Option, + /// Useful for IME. + pub ime: Option, /// The difference in the widget tree since last frame. /// @@ -143,7 +158,7 @@ impl PlatformOutput { copied_text, mut events, mutable_text_under_cursor, - text_cursor_pos, + ime, #[cfg(feature = "accesskit")] accesskit_update, } = newer; @@ -157,7 +172,7 @@ impl PlatformOutput { } self.events.append(&mut events); self.mutable_text_under_cursor = mutable_text_under_cursor; - self.text_cursor_pos = text_cursor_pos.or(self.text_cursor_pos); + self.ime = ime.or(self.ime); #[cfg(feature = "accesskit")] { diff --git a/crates/egui/src/widgets/text_edit/builder.rs b/crates/egui/src/widgets/text_edit/builder.rs index d96a8a216f7..cccff16eb8a 100644 --- a/crates/egui/src/widgets/text_edit/builder.rs +++ b/crates/egui/src/widgets/text_edit/builder.rs @@ -688,7 +688,7 @@ impl<'t> TextEdit<'t> { paint_cursor_selection(ui, &painter, text_draw_pos, &galley, &cursor_range); if text.is_mutable() { - let cursor_pos = paint_cursor_end( + let cursor_rect = paint_cursor_end( ui, row_height, &painter, @@ -699,23 +699,14 @@ impl<'t> TextEdit<'t> { let is_fully_visible = ui.clip_rect().contains_rect(rect); // TODO: remove this HACK workaround for https://github.com/emilk/egui/issues/1531 if (response.changed || selection_changed) && !is_fully_visible { - ui.scroll_to_rect(cursor_pos, None); // keep cursor in view + ui.scroll_to_rect(cursor_rect, None); // keep cursor in view } if interactive { - // eframe web uses `text_cursor_pos` when showing IME, - // so only set it when text is editable and visible! - // But `winit` and `egui_web` differs in how to set the - // position of IME. - if cfg!(target_arch = "wasm32") { - ui.ctx().output_mut(|o| { - o.text_cursor_pos = Some(cursor_pos.left_top()); - }); - } else { - ui.ctx().output_mut(|o| { - o.text_cursor_pos = Some(cursor_pos.left_bottom()); - }); - } + // For IME, so only set it when text is editable and visible! + ui.ctx().output_mut(|o| { + o.ime = Some(crate::output::IMEOutput { rect, cursor_rect }); + }); } } } From 98ae3efb81fa3b3d93d413da83b944680d7b3724 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 13:19:12 +0100 Subject: [PATCH 28/46] Fix typo --- crates/egui/src/data/output.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/egui/src/data/output.rs b/crates/egui/src/data/output.rs index 70b3a30e13f..d35f014a5b7 100644 --- a/crates/egui/src/data/output.rs +++ b/crates/egui/src/data/output.rs @@ -62,7 +62,7 @@ impl FullOutput { } } -/// Information about text beeing edited. +/// Information about text being edited. /// /// Useful for IME. #[derive(Copy, Clone, Debug, PartialEq, Eq)] From 9d0037f46ef9484b1c724a6473fc37982228c658 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 13:27:52 +0100 Subject: [PATCH 29/46] Don't treat `cmd+C` etc as text input on Mac --- crates/egui-winit/src/lib.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 3d4bb2b6a56..89eb8781ea1 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -672,9 +672,14 @@ impl State { } if let Some(text) = &input.text { - self.egui_input - .events - .push(egui::Event::Text(text.to_string())); + // On Mac we get here when the user presses Cmd-C (copy), ctrl-W, etc. + // We need to ignore these characters that are side-effects of commands. + let is_mac_cmd = cfg!(target_os = "macos") && self.egui_input.modifiers.mac_cmd; + if !is_mac_cmd { + self.egui_input + .events + .push(egui::Event::Text(text.to_string())); + } } false From dc1a95ecfbb8984133ea1737f18163cd68e0ce52 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 14:39:13 +0100 Subject: [PATCH 30/46] Output logical keys from winit, and document that fact --- crates/eframe/src/web/events.rs | 2 + crates/egui-winit/src/lib.rs | 192 ++++++++++++++++++++++++++------ crates/egui/src/data/input.rs | 12 ++ 3 files changed, 175 insertions(+), 31 deletions(-) diff --git a/crates/eframe/src/web/events.rs b/crates/eframe/src/web/events.rs index 9bb5c0f885a..2418bed95c5 100644 --- a/crates/eframe/src/web/events.rs +++ b/crates/eframe/src/web/events.rs @@ -91,6 +91,7 @@ pub(crate) fn install_document_events(runner_ref: &WebRunner) -> Result<(), JsVa if let Some(key) = egui_key { runner.input.raw.events.push(egui::Event::Key { key, + physical_key: None, // TODO pressed: true, repeat: false, // egui will fill this in for us! modifiers, @@ -157,6 +158,7 @@ pub(crate) fn install_document_events(runner_ref: &WebRunner) -> Result<(), JsVa if let Some(key) = translate_key(&event.key()) { runner.input.raw.events.push(egui::Event::Key { key, + physical_key: None, // TODO pressed: false, repeat: false, modifiers, diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 89eb8781ea1..bdb81636907 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -637,20 +637,53 @@ impl State { } } - fn on_keyboard_input(&mut self, input: &winit::event::KeyEvent) -> bool { - if let winit::keyboard::PhysicalKey::Code(keycode) = input.physical_key { - let pressed = input.state == winit::event::ElementState::Pressed; + fn on_keyboard_input(&mut self, event: &winit::event::KeyEvent) -> bool { + let winit::event::KeyEvent { + // Represents the position of a key independent of the currently active layout. + // + // It also uniquely identifies the physical key (i.e. it's mostly synonymous with a scancode). + // The most prevalent use case for this is games. For example the default keys for the player + // to move around might be the W, A, S, and D keys on a US layout. The position of these keys + // is more important than their label, so they should map to Z, Q, S, and D on an "AZERTY" + // layout. (This value is `KeyCode::KeyW` for the Z key on an AZERTY layout.) + physical_key, + + // Represents the results of a keymap, i.e. what character a certain key press represents. + // When telling users "Press Ctrl-F to find", this is where we should + // look for the "F" key, because they may have a dvorak layout on + // a qwerty keyboard, and so the logical "F" character may not be located on the physical `KeyCode::KeyF` position. + logical_key, + + text, + + state, + + location: _, // e.g. is it on the numpad? + repeat: _, // egui will figure this out for us + .. + } = event; + + let pressed = *state == winit::event::ElementState::Pressed; + + let physical_key = if let winit::keyboard::PhysicalKey::Code(keycode) = *physical_key { + key_from_key_code(keycode) + } else { + None + }; + let logical_key = key_from_winit_key(logical_key); + + if let Some(logical_key) = logical_key { if pressed { // KeyCode::Paste etc in winit are broken/untrustworthy, // so we detect these things manually: - if is_cut_command(self.egui_input.modifiers, keycode) { + if is_cut_command(self.egui_input.modifiers, logical_key) { self.egui_input.events.push(egui::Event::Cut); return true; - } else if is_copy_command(self.egui_input.modifiers, keycode) { + } else if is_copy_command(self.egui_input.modifiers, logical_key) { self.egui_input.events.push(egui::Event::Copy); return true; - } else if is_paste_command(self.egui_input.modifiers, keycode) { + } else if is_paste_command(self.egui_input.modifiers, logical_key) { if let Some(contents) = self.clipboard.get() { let contents = contents.replace("\r\n", "\n"); if !contents.is_empty() { @@ -661,17 +694,16 @@ impl State { } } - if let Some(key) = translate_key_code(keycode) { - self.egui_input.events.push(egui::Event::Key { - key, - pressed, - repeat: false, // egui will fill this in for us! - modifiers: self.egui_input.modifiers, - }); - } + self.egui_input.events.push(egui::Event::Key { + key: logical_key, + physical_key, + pressed, + repeat: false, // egui will fill this in for us! + modifiers: self.egui_input.modifiers, + }); } - if let Some(text) = &input.text { + if let Some(text) = &text { // On Mac we get here when the user presses Cmd-C (copy), ctrl-W, etc. // We need to ignore these characters that are side-effects of commands. let is_mac_cmd = cfg!(target_os = "macos") && self.egui_input.modifiers.mac_cmd; @@ -871,25 +903,19 @@ fn open_url_in_browser(_url: &str) { } } -fn is_cut_command(modifiers: egui::Modifiers, keycode: winit::keyboard::KeyCode) -> bool { - (modifiers.command && keycode == winit::keyboard::KeyCode::KeyX) - || (cfg!(target_os = "windows") - && modifiers.shift - && keycode == winit::keyboard::KeyCode::Delete) +fn is_cut_command(modifiers: egui::Modifiers, keycode: egui::Key) -> bool { + (modifiers.command && keycode == egui::Key::X) + || (cfg!(target_os = "windows") && modifiers.shift && keycode == egui::Key::Delete) } -fn is_copy_command(modifiers: egui::Modifiers, keycode: winit::keyboard::KeyCode) -> bool { - (modifiers.command && keycode == winit::keyboard::KeyCode::KeyC) - || (cfg!(target_os = "windows") - && modifiers.ctrl - && keycode == winit::keyboard::KeyCode::Insert) +fn is_copy_command(modifiers: egui::Modifiers, keycode: egui::Key) -> bool { + (modifiers.command && keycode == egui::Key::C) + || (cfg!(target_os = "windows") && modifiers.ctrl && keycode == egui::Key::Insert) } -fn is_paste_command(modifiers: egui::Modifiers, keycode: winit::keyboard::KeyCode) -> bool { - (modifiers.command && keycode == winit::keyboard::KeyCode::KeyV) - || (cfg!(target_os = "windows") - && modifiers.shift - && keycode == winit::keyboard::KeyCode::Insert) +fn is_paste_command(modifiers: egui::Modifiers, keycode: egui::Key) -> bool { + (modifiers.command && keycode == egui::Key::V) + || (cfg!(target_os = "windows") && modifiers.shift && keycode == egui::Key::Insert) } fn translate_mouse_button(button: winit::event::MouseButton) -> Option { @@ -903,7 +929,111 @@ fn translate_mouse_button(button: winit::event::MouseButton) -> Option Option { +fn key_from_winit_key(key: &winit::keyboard::Key) -> Option { + match key { + winit::keyboard::Key::Named(named_key) => key_from_named_key(*named_key), + winit::keyboard::Key::Character(str) => key_from_string(str.as_str()), + winit::keyboard::Key::Unidentified(_) | winit::keyboard::Key::Dead(_) => None, + } +} + +fn key_from_named_key(named_key: winit::keyboard::NamedKey) -> Option { + use egui::Key; + use winit::keyboard::NamedKey; + + match named_key { + NamedKey::Enter => Some(Key::Enter), + NamedKey::Tab => Some(Key::Tab), + NamedKey::Space => Some(Key::Space), + NamedKey::ArrowDown => Some(Key::ArrowDown), + NamedKey::ArrowLeft => Some(Key::ArrowLeft), + NamedKey::ArrowRight => Some(Key::ArrowRight), + NamedKey::ArrowUp => Some(Key::ArrowUp), + NamedKey::End => Some(Key::End), + NamedKey::Home => Some(Key::Home), + NamedKey::PageDown => Some(Key::PageDown), + NamedKey::PageUp => Some(Key::PageUp), + NamedKey::Backspace => Some(Key::Backspace), + NamedKey::Delete => Some(Key::Delete), + NamedKey::Insert => Some(Key::Insert), + NamedKey::Escape => Some(Key::Escape), + NamedKey::F1 => Some(Key::F1), + NamedKey::F2 => Some(Key::F2), + NamedKey::F3 => Some(Key::F3), + NamedKey::F4 => Some(Key::F4), + NamedKey::F5 => Some(Key::F5), + NamedKey::F6 => Some(Key::F6), + NamedKey::F7 => Some(Key::F7), + NamedKey::F8 => Some(Key::F8), + NamedKey::F9 => Some(Key::F9), + NamedKey::F10 => Some(Key::F10), + NamedKey::F11 => Some(Key::F11), + NamedKey::F12 => Some(Key::F12), + NamedKey::F13 => Some(Key::F13), + NamedKey::F14 => Some(Key::F14), + NamedKey::F15 => Some(Key::F15), + NamedKey::F16 => Some(Key::F16), + NamedKey::F17 => Some(Key::F17), + NamedKey::F18 => Some(Key::F18), + NamedKey::F19 => Some(Key::F19), + NamedKey::F20 => Some(Key::F20), + _ => { + log::debug!("Unknown key: {named_key:?}"); + None + } + } +} + +fn key_from_string(as_str: &str) -> Option { + use egui::Key; + + match as_str { + "-" => Some(Key::Minus), + "+" | "=" => Some(Key::PlusEquals), + + "0" => Some(Key::Num0), + "1" => Some(Key::Num1), + "2" => Some(Key::Num2), + "3" => Some(Key::Num3), + "4" => Some(Key::Num4), + "5" => Some(Key::Num5), + "6" => Some(Key::Num6), + "7" => Some(Key::Num7), + "8" => Some(Key::Num8), + "9" => Some(Key::Num9), + + "a" | "A" => Some(Key::A), + "b" | "B" => Some(Key::B), + "c" | "C" => Some(Key::C), + "d" | "D" => Some(Key::D), + "e" | "E" => Some(Key::E), + "f" | "F" => Some(Key::F), + "g" | "G" => Some(Key::G), + "h" | "H" => Some(Key::H), + "i" | "I" => Some(Key::I), + "j" | "J" => Some(Key::J), + "k" | "K" => Some(Key::K), + "l" | "L" => Some(Key::L), + "m" | "M" => Some(Key::M), + "n" | "N" => Some(Key::N), + "o" | "O" => Some(Key::O), + "p" | "P" => Some(Key::P), + "q" | "Q" => Some(Key::Q), + "r" | "R" => Some(Key::R), + "s" | "S" => Some(Key::S), + "t" | "T" => Some(Key::T), + "u" | "U" => Some(Key::U), + "v" | "V" => Some(Key::V), + "w" | "W" => Some(Key::W), + "x" | "X" => Some(Key::X), + "y" | "Y" => Some(Key::Y), + "z" | "Z" => Some(Key::Z), + + _ => None, + } +} + +fn key_from_key_code(key: winit::keyboard::KeyCode) -> Option { use egui::Key; use winit::keyboard::KeyCode; diff --git a/crates/egui/src/data/input.rs b/crates/egui/src/data/input.rs index 50073338b3c..0609b38d636 100644 --- a/crates/egui/src/data/input.rs +++ b/crates/egui/src/data/input.rs @@ -361,8 +361,20 @@ pub enum Event { /// A key was pressed or released. Key { + /// The logical key, heeding the users keymap. + /// + /// For instance, if the user is using Dvorak keyboard layout, + /// this will take that into account. key: Key, + /// The physical key, corresponding to the actual position on the keyboard. + /// + /// This ignored keymaps, so it is not recommended to use this. + /// The only thing it makes sense for is things like games, + /// where e.g. the physical location of WSAD on QWERTY should always map to movement, + /// even if the user is using Dvorak or AZERTY. + physical_key: Option, + /// Was it pressed or released? pressed: bool, From 054cedcbe44fa57f53eb4ecdb14e238caf589437 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 15:17:16 +0100 Subject: [PATCH 31/46] Fix Windows build --- crates/eframe/src/native/run.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index c6c0a860ef5..dd0e0905868 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -210,7 +210,7 @@ fn run_and_return( // we only apply this approach on Windows to minimize the affect. #[cfg(target_os = "windows")] { - event_loop.run_return(|_, _, control_flow| { + event_loop.run_on_demand(|_, _, control_flow| { control_flow.set_exit(); }); } From 4cfa02a57e99557ae10b238082af34cdfbc3d358 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 15:25:11 +0100 Subject: [PATCH 32/46] Fix windows build for real --- crates/eframe/src/native/run.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index dd0e0905868..ac5e96658ac 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -210,8 +210,8 @@ fn run_and_return( // we only apply this approach on Windows to minimize the affect. #[cfg(target_os = "windows")] { - event_loop.run_on_demand(|_, _, control_flow| { - control_flow.set_exit(); + event_loop.run_on_demand(|_, event_loop_window_target| { + event_loop_window_target.exit(); }); } From 98053178360901057419ba8927d6f719373dd028 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 15:28:49 +0100 Subject: [PATCH 33/46] No really, fix the Windows issue --- crates/eframe/src/native/run.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index ac5e96658ac..bc908ff094e 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -210,9 +210,11 @@ fn run_and_return( // we only apply this approach on Windows to minimize the affect. #[cfg(target_os = "windows")] { - event_loop.run_on_demand(|_, event_loop_window_target| { - event_loop_window_target.exit(); - }); + event_loop + .run_on_demand(|_, event_loop_window_target| { + event_loop_window_target.exit(); + }) + .ok(); } returned_result From dfa6676607941819aaff657747b377ad37e86a67 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 15:31:04 +0100 Subject: [PATCH 34/46] Remove outdated(?) windows hack --- crates/egui_glow/examples/pure_glow.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/egui_glow/examples/pure_glow.rs b/crates/egui_glow/examples/pure_glow.rs index f9949d3fb7d..6f024779584 100644 --- a/crates/egui_glow/examples/pure_glow.rs +++ b/crates/egui_glow/examples/pure_glow.rs @@ -218,12 +218,6 @@ fn main() { }; match event { - // Platform-dependent event handlers to workaround a winit bug - // See: https://github.com/rust-windowing/winit/issues/987 - // See: https://github.com/rust-windowing/winit/issues/1619 - // winit::event::Event::RedrawEventsCleared if cfg!(target_os = "windows") => redraw(), - // winit::event::Event::RedrawRequested(_) if !cfg!(target_os = "windows") => redraw(), - // TODO: Adopt to above comment (if still relevant) winit::event::Event::WindowEvent { event, .. } => { use winit::event::WindowEvent; if matches!(event, WindowEvent::CloseRequested | WindowEvent::Destroyed) { From 666e099f06362525c25d7328c6ab9813406b8f91 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 17:42:44 +0100 Subject: [PATCH 35/46] Add `wgpu` feature to `multiple_viewports` example --- examples/multiple_viewports/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/multiple_viewports/Cargo.toml b/examples/multiple_viewports/Cargo.toml index 81e7c7b2d28..e13bb487ca2 100644 --- a/examples/multiple_viewports/Cargo.toml +++ b/examples/multiple_viewports/Cargo.toml @@ -7,6 +7,8 @@ edition = "2021" rust-version = "1.72" publish = false +[features] +wgpu = ["eframe/wgpu"] [dependencies] eframe = { path = "../../crates/eframe", features = [ From b74bfd97ee95309cd8b2d5f73981548aa85c4c14 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 18:09:39 +0100 Subject: [PATCH 36/46] Code cleanup and better logging --- crates/eframe/src/native/glow_integration.rs | 94 ++++++++++---------- crates/eframe/src/native/run.rs | 10 ++- crates/eframe/src/native/wgpu_integration.rs | 2 + crates/egui-winit/src/lib.rs | 2 +- 4 files changed, 58 insertions(+), 50 deletions(-) diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index d6893fd867f..16e868ce20b 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -122,6 +122,8 @@ struct Viewport { /// None for immediate viewports. viewport_ui_cb: Option>, + // These three live and die together. + // TODO(emilk): clump them together into one struct! gl_surface: Option>, window: Option>, egui_winit: Option, @@ -170,12 +172,12 @@ impl GlowWinitApp { }; // Creates the window - must come before we create our glow context - glutin_window_context.on_resume(event_loop)?; + glutin_window_context.initialize_all_viewports(event_loop)?; - if let Some(viewport) = glutin_window_context.viewports.get(&ViewportId::ROOT) { - if let Some(window) = &viewport.window { - epi_integration::apply_window_settings(window, window_settings); - } + { + let viewport = &glutin_window_context.viewports[&ViewportId::ROOT]; + let window = viewport.window.as_ref().unwrap(); // Can't fail - we just called `initialize_all_viewports` + epi_integration::apply_window_settings(window, window_settings); } let gl = unsafe { @@ -417,9 +419,14 @@ impl WinitApp for GlowWinitApp { Ok(match event { winit::event::Event::Resumed => { + log::debug!("Event::Resumed"); + let running = if let Some(running) = &mut self.running { // not the first resume event. create whatever you need. - running.glutin.borrow_mut().on_resume(event_loop)?; + running + .glutin + .borrow_mut() + .initialize_all_viewports(event_loop)?; running } else { // first resume event. @@ -427,13 +434,8 @@ impl WinitApp for GlowWinitApp { // and just run the on_resume fn of gl_window self.init_run_state(event_loop)? }; - let window_id = running - .glutin - .borrow() - .window_from_viewport - .get(&ViewportId::ROOT) - .copied(); - EventResult::RepaintNow(window_id.unwrap()) + let window_id = running.glutin.borrow().window_from_viewport[&ViewportId::ROOT]; + EventResult::RepaintNow(window_id) } winit::event::Event::Suspended => { @@ -931,37 +933,30 @@ impl GlutinWindowContext { focused_viewport: Some(ViewportId::ROOT), }; - slf.on_resume(event_loop)?; + slf.initialize_all_viewports(event_loop)?; Ok(slf) } - /// This will be run after `new`. on android, it might be called multiple times over the course of the app's lifetime. - /// roughly, - /// 1. check if window already exists. otherwise, create one now. - /// 2. create attributes for surface creation. - /// 3. create surface. - /// 4. make surface and context current. - /// - /// we presently assume that we will - fn on_resume(&mut self, event_loop: &EventLoopWindowTarget) -> Result<()> { + /// Create a surface, window, and winit integration for all viewports lacking any of that. + fn initialize_all_viewports( + &mut self, + event_loop: &EventLoopWindowTarget, + ) -> Result<()> { crate::profile_function!(); - let viewports: Vec = self - .viewports - .iter() - .filter(|(_, viewport)| viewport.gl_surface.is_none()) - .map(|(id, _)| *id) - .collect(); + let viewports: Vec = self.viewports.keys().copied().collect(); for viewport_id in viewports { - self.init_viewport(viewport_id, event_loop)?; + self.initalize_viewport(viewport_id, event_loop)?; } + Ok(()) } + /// Create a surface, window, and winit integration for the viewport, if missing. #[allow(unsafe_code)] - pub(crate) fn init_viewport( + pub(crate) fn initalize_viewport( &mut self, viewport_id: ViewportId, event_loop: &EventLoopWindowTarget, @@ -976,7 +971,7 @@ impl GlutinWindowContext { let window = if let Some(window) = &mut viewport.window { window } else { - log::trace!("Window doesn't exist yet. Creating one now with finalize_window"); + log::debug!("Creating a window for viewport {viewport_id:?}"); let window = glutin_winit::finalize_window( event_loop, create_winit_window_builder(&self.egui_ctx, event_loop, viewport.builder.clone()), @@ -988,7 +983,19 @@ impl GlutinWindowContext { viewport.window.insert(Rc::new(window)) }; - { + viewport.egui_winit.get_or_insert_with(|| { + log::debug!("Initializing egui_winit for viewport {viewport_id:?}"); + egui_winit::State::new( + viewport_id, + event_loop, + Some(window.scale_factor() as f32), + self.max_texture_side, + ) + }); + + if viewport.gl_surface.is_none() { + log::debug!("Creating a gl_surface for viewport {viewport_id:?}"); + // surface attributes let (width_px, height_px): (u32, u32) = window.inner_size().into(); let width_px = std::num::NonZeroU32::new(width_px.at_least(1)).unwrap(); @@ -1028,23 +1035,16 @@ impl GlutinWindowContext { // we will reach this point only once in most platforms except android. // create window/surface/make context current once and just use them forever. - viewport.egui_winit.get_or_insert_with(|| { - egui_winit::State::new( - viewport_id, - event_loop, - Some(window.scale_factor() as f32), - self.max_texture_side, - ) - }); - viewport.gl_surface = Some(gl_surface); + self.current_gl_context = Some(current_gl_context); - self.viewport_from_window - .insert(window.id(), viewport.ids.this); - self.window_from_viewport - .insert(viewport.ids.this, window.id()); } + self.viewport_from_window + .insert(window.id(), viewport.ids.this); + self.window_from_viewport + .insert(viewport.ids.this, window.id()); + Ok(()) } @@ -1279,7 +1279,7 @@ fn render_immediate_viewport( if viewport.gl_surface.is_none() { glutin - .init_viewport(ids.this, event_loop) + .initalize_viewport(ids.this, event_loop) .expect("Failed to initialize window in egui::Context::show_viewport_immediate"); } } diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index bc908ff094e..3c33ef7da20 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -143,7 +143,10 @@ fn run_and_return( event_loop_window_target.set_control_flow(ControlFlow::Wait); } EventResult::RepaintNow(window_id) => { - log::trace!("RepaintNow caused by {}", short_event_description(&event)); + log::trace!( + "RepaintNow of {window_id:?} caused by {}", + short_event_description(&event) + ); if cfg!(target_os = "windows") { // Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 windows_next_repaint_times.remove(&window_id); @@ -155,7 +158,10 @@ fn run_and_return( } } EventResult::RepaintNext(window_id) => { - log::trace!("RepaintNext caused by {}", short_event_description(&event)); + log::trace!( + "RepaintNext of {window_id:?} caused by {}", + short_event_description(&event) + ); windows_next_repaint_times.insert(window_id, Instant::now()); } EventResult::RepaintAt(window_id, repaint_time) => { diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index ffd6c4ffba4..5e2cbc265fc 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -372,6 +372,8 @@ impl WinitApp for WgpuWinitApp { Ok(match event { winit::event::Event::Resumed => { + log::debug!("Event::Resumed"); + let running = if let Some(running) = &self.running { running } else { diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index bdb81636907..218a2f86935 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -978,7 +978,7 @@ fn key_from_named_key(named_key: winit::keyboard::NamedKey) -> Option NamedKey::F19 => Some(Key::F19), NamedKey::F20 => Some(Key::F20), _ => { - log::debug!("Unknown key: {named_key:?}"); + log::trace!("Unknown key: {named_key:?}"); None } } From 9976c7b5fa3c26cddef64a147360297fea09764b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 18:33:07 +0100 Subject: [PATCH 37/46] Fix secondary viewports with glow backend --- crates/eframe/src/native/glow_integration.rs | 42 ++++++++++++------- crates/eframe/src/native/run.rs | 8 ++-- crates/eframe/src/native/wgpu_integration.rs | 6 ++- crates/eframe/src/native/winit_integration.rs | 6 ++- 4 files changed, 40 insertions(+), 22 deletions(-) diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index 16e868ce20b..3b9b2972601 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -172,7 +172,7 @@ impl GlowWinitApp { }; // Creates the window - must come before we create our glow context - glutin_window_context.initialize_all_viewports(event_loop)?; + glutin_window_context.initialize_all_windows(event_loop)?; { let viewport = &glutin_window_context.viewports[&ViewportId::ROOT]; @@ -402,9 +402,13 @@ impl WinitApp for GlowWinitApp { } } - fn run_ui_and_paint(&mut self, window_id: WindowId) -> EventResult { + fn run_ui_and_paint( + &mut self, + event_loop: &EventLoopWindowTarget, + window_id: WindowId, + ) -> EventResult { if let Some(running) = &mut self.running { - running.run_ui_and_paint(window_id) + running.run_ui_and_paint(event_loop, window_id) } else { EventResult::Wait } @@ -422,16 +426,14 @@ impl WinitApp for GlowWinitApp { log::debug!("Event::Resumed"); let running = if let Some(running) = &mut self.running { - // not the first resume event. create whatever you need. + // Not the first resume event. Create all outstanding windows. running .glutin .borrow_mut() - .initialize_all_viewports(event_loop)?; + .initialize_all_windows(event_loop)?; running } else { - // first resume event. - // we can actually move this outside of event loop. - // and just run the on_resume fn of gl_window + // First resume event. Created our root window etc. self.init_run_state(event_loop)? }; let window_id = running.glutin.borrow().window_from_viewport[&ViewportId::ROOT]; @@ -480,7 +482,11 @@ impl WinitApp for GlowWinitApp { } impl GlowWinitRunning { - fn run_ui_and_paint(&mut self, window_id: WindowId) -> EventResult { + fn run_ui_and_paint( + &mut self, + event_loop: &EventLoopWindowTarget, + window_id: WindowId, + ) -> EventResult { crate::profile_function!(); let Some(viewport_id) = self @@ -654,7 +660,7 @@ impl GlowWinitRunning { std::thread::sleep(std::time::Duration::from_millis(10)); } - glutin.handle_viewport_output(&integration.egui_ctx, viewport_output); + glutin.handle_viewport_output(event_loop, &integration.egui_ctx, viewport_output); if integration.should_close() { EventResult::Exit @@ -933,13 +939,13 @@ impl GlutinWindowContext { focused_viewport: Some(ViewportId::ROOT), }; - slf.initialize_all_viewports(event_loop)?; + slf.initialize_all_windows(event_loop)?; Ok(slf) } /// Create a surface, window, and winit integration for all viewports lacking any of that. - fn initialize_all_viewports( + fn initialize_all_windows( &mut self, event_loop: &EventLoopWindowTarget, ) -> Result<()> { @@ -948,7 +954,7 @@ impl GlutinWindowContext { let viewports: Vec = self.viewports.keys().copied().collect(); for viewport_id in viewports { - self.initalize_viewport(viewport_id, event_loop)?; + self.initalize_window(viewport_id, event_loop)?; } Ok(()) @@ -956,7 +962,7 @@ impl GlutinWindowContext { /// Create a surface, window, and winit integration for the viewport, if missing. #[allow(unsafe_code)] - pub(crate) fn initalize_viewport( + pub(crate) fn initalize_window( &mut self, viewport_id: ViewportId, event_loop: &EventLoopWindowTarget, @@ -1109,6 +1115,7 @@ impl GlutinWindowContext { fn handle_viewport_output( &mut self, + event_loop: &EventLoopWindowTarget, egui_ctx: &egui::Context, viewport_output: ViewportIdMap, ) { @@ -1153,6 +1160,9 @@ impl GlutinWindowContext { } } + // Create windows for any new viewports: + self.initialize_all_windows(event_loop); + // GC old viewports self.viewports .retain(|id, _| active_viewports_ids.contains(id)); @@ -1279,7 +1289,7 @@ fn render_immediate_viewport( if viewport.gl_surface.is_none() { glutin - .initalize_viewport(ids.this, event_loop) + .initalize_window(ids.this, event_loop) .expect("Failed to initialize window in egui::Context::show_viewport_immediate"); } } @@ -1385,7 +1395,7 @@ fn render_immediate_viewport( winit_state.handle_platform_output(window, egui_ctx, platform_output); - glutin.handle_viewport_output(egui_ctx, viewport_output); + glutin.handle_viewport_output(event_loop, egui_ctx, viewport_output); } #[cfg(feature = "__screenshot")] diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 3c33ef7da20..95e355a1048 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -96,7 +96,7 @@ fn run_and_return( window_id, } => { windows_next_repaint_times.remove(window_id); - winit_app.run_ui_and_paint(*window_id) + winit_app.run_ui_and_paint(event_loop_window_target, *window_id) } winit::event::Event::UserEvent(UserEvent::RequestRepaint { @@ -151,7 +151,7 @@ fn run_and_return( // Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 windows_next_repaint_times.remove(&window_id); - winit_app.run_ui_and_paint(window_id); + winit_app.run_ui_and_paint(event_loop_window_target, window_id); } else { // Fix for https://github.com/emilk/egui/issues/2425 windows_next_repaint_times.insert(window_id, Instant::now()); @@ -256,7 +256,7 @@ fn run_and_exit( window_id, } => { windows_next_repaint_times.remove(window_id); - winit_app.run_ui_and_paint(*window_id) + winit_app.run_ui_and_paint(event_loop_window_target, *window_id) } winit::event::Event::UserEvent(UserEvent::RequestRepaint { @@ -305,7 +305,7 @@ fn run_and_exit( // Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280 windows_next_repaint_times.remove(&window_id); - winit_app.run_ui_and_paint(window_id); + winit_app.run_ui_and_paint(event_loop_window_target, window_id); } else { // Fix for https://github.com/emilk/egui/issues/2425 windows_next_repaint_times.insert(window_id, Instant::now()); diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index 5e2cbc265fc..d6474587d5a 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -353,7 +353,11 @@ impl WinitApp for WgpuWinitApp { } } - fn run_ui_and_paint(&mut self, window_id: WindowId) -> EventResult { + fn run_ui_and_paint( + &mut self, + event_loop: &EventLoopWindowTarget, + window_id: WindowId, + ) -> EventResult { if let Some(running) = &mut self.running { running.run_ui_and_paint(window_id) } else { diff --git a/crates/eframe/src/native/winit_integration.rs b/crates/eframe/src/native/winit_integration.rs index fc4910b4c64..a7e4bb384b3 100644 --- a/crates/eframe/src/native/winit_integration.rs +++ b/crates/eframe/src/native/winit_integration.rs @@ -74,7 +74,11 @@ pub trait WinitApp { fn save_and_destroy(&mut self); - fn run_ui_and_paint(&mut self, window_id: WindowId) -> EventResult; + fn run_ui_and_paint( + &mut self, + event_loop: &EventLoopWindowTarget, + window_id: WindowId, + ) -> EventResult; fn on_event( &mut self, From 9cb45f1063d708f564147112b1b20de70714e84e Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 18:46:32 +0100 Subject: [PATCH 38/46] Clean up code around window creation --- crates/eframe/src/native/glow_integration.rs | 46 ++++++++++---------- crates/eframe/src/native/wgpu_integration.rs | 32 ++++++++------ 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index 3b9b2972601..bf7421a89c6 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -172,7 +172,7 @@ impl GlowWinitApp { }; // Creates the window - must come before we create our glow context - glutin_window_context.initialize_all_windows(event_loop)?; + glutin_window_context.initialize_window(ViewportId::ROOT, event_loop)?; { let viewport = &glutin_window_context.viewports[&ViewportId::ROOT]; @@ -430,7 +430,7 @@ impl WinitApp for GlowWinitApp { running .glutin .borrow_mut() - .initialize_all_windows(event_loop)?; + .initialize_all_windows(event_loop); running } else { // First resume event. Created our root window etc. @@ -939,30 +939,29 @@ impl GlutinWindowContext { focused_viewport: Some(ViewportId::ROOT), }; - slf.initialize_all_windows(event_loop)?; + slf.initialize_window(ViewportId::ROOT, event_loop)?; Ok(slf) } /// Create a surface, window, and winit integration for all viewports lacking any of that. - fn initialize_all_windows( - &mut self, - event_loop: &EventLoopWindowTarget, - ) -> Result<()> { + /// + /// Errors will be logged. + fn initialize_all_windows(&mut self, event_loop: &EventLoopWindowTarget) { crate::profile_function!(); let viewports: Vec = self.viewports.keys().copied().collect(); for viewport_id in viewports { - self.initalize_window(viewport_id, event_loop)?; + if let Err(err) = self.initialize_window(viewport_id, event_loop) { + log::error!("Failed to initialize a window for viewport {viewport_id:?}: {err}"); + } } - - Ok(()) } /// Create a surface, window, and winit integration for the viewport, if missing. #[allow(unsafe_code)] - pub(crate) fn initalize_window( + pub(crate) fn initialize_window( &mut self, viewport_id: ViewportId, event_loop: &EventLoopWindowTarget, @@ -1046,10 +1045,8 @@ impl GlutinWindowContext { self.current_gl_context = Some(current_gl_context); } - self.viewport_from_window - .insert(window.id(), viewport.ids.this); - self.window_from_viewport - .insert(viewport.ids.this, window.id()); + self.viewport_from_window.insert(window.id(), viewport_id); + self.window_from_viewport.insert(viewport_id, window.id()); Ok(()) } @@ -1274,10 +1271,12 @@ fn render_immediate_viewport( viewport_ui_cb, } = immediate_viewport; + let viewport_id = ids.this; + { let mut glutin = glutin.borrow_mut(); - let viewport = initialize_or_update_viewport( + initialize_or_update_viewport( egui_ctx, &mut glutin.viewports, ids, @@ -1287,17 +1286,18 @@ fn render_immediate_viewport( None, ); - if viewport.gl_surface.is_none() { - glutin - .initalize_window(ids.this, event_loop) - .expect("Failed to initialize window in egui::Context::show_viewport_immediate"); + if let Err(err) = glutin.initialize_window(viewport_id, event_loop) { + log::error!( + "Failed to initialize a window for immediate viewport {viewport_id:?}: {err}" + ); + return; } } let input = { let mut glutin = glutin.borrow_mut(); - let Some(viewport) = glutin.viewports.get_mut(&ids.this) else { + let Some(viewport) = glutin.viewports.get_mut(&viewport_id) else { return; }; viewport.update_viewport_info(); @@ -1342,7 +1342,7 @@ fn render_immediate_viewport( .. } = &mut *glutin; - let Some(viewport) = viewports.get_mut(&ids.this) else { + let Some(viewport) = viewports.get_mut(&viewport_id) else { return; }; viewport.info.events.clear(); // they should have been processed @@ -1373,7 +1373,7 @@ fn render_immediate_viewport( let current_gl_context = current_gl_context.as_ref().unwrap(); if !gl_surface.is_current(current_gl_context) { - log::error!("egui::show_viewport_immediate: viewport {:?} ({:?}) is not created in main thread, try to use wgpu!", viewport.ids.this, viewport.builder.title); + log::error!("egui::show_viewport_immediate: viewport {:?} ({:?}) is not created in main thread, try to use wgpu!", viewport_id, viewport.builder.title); } let gl = &painter.gl().clone(); diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index d6474587d5a..dbf0de77514 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -117,7 +117,8 @@ impl WgpuWinitApp { } } - fn build_windows(&mut self, event_loop: &EventLoopWindowTarget) { + /// Create a window for all viewports lacking one. + fn initialized_all_windows(&mut self, event_loop: &EventLoopWindowTarget) { let Some(running) = &mut self.running else { return; }; @@ -130,14 +131,12 @@ impl WgpuWinitApp { } = &mut *shared; for viewport in viewports.values_mut() { - if viewport.window.is_none() { - viewport.init_window( - &running.integration.egui_ctx, - viewport_from_window, - painter, - event_loop, - ); - } + viewport.initialize_window( + event_loop, + &running.integration.egui_ctx, + viewport_from_window, + painter, + ); } } @@ -358,6 +357,8 @@ impl WinitApp for WgpuWinitApp { event_loop: &EventLoopWindowTarget, window_id: WindowId, ) -> EventResult { + self.initialized_all_windows(event_loop); + if let Some(running) = &mut self.running { running.run_ui_and_paint(window_id) } else { @@ -372,7 +373,7 @@ impl WinitApp for WgpuWinitApp { ) -> Result { crate::profile_function!(winit_integration::short_event_description(event)); - self.build_windows(event_loop); + self.initialized_all_windows(event_loop); Ok(match event { winit::event::Event::Resumed => { @@ -769,13 +770,18 @@ impl WgpuWinitRunning { } impl Viewport { - fn init_window( + /// Create winit window, if needed. + fn initialize_window( &mut self, + event_loop: &EventLoopWindowTarget, egui_ctx: &egui::Context, windows_id: &mut HashMap, painter: &mut egui_wgpu::winit::Painter, - event_loop: &EventLoopWindowTarget, ) { + if self.window.is_some() { + return; // we already have one + } + crate::profile_function!(); let viewport_id = self.ids.this; @@ -884,7 +890,7 @@ fn render_immediate_viewport( None, ); if viewport.window.is_none() { - viewport.init_window(egui_ctx, viewport_from_window, painter, event_loop); + viewport.initialize_window(event_loop, egui_ctx, viewport_from_window, painter); } viewport.update_viewport_info(); From 43b18ce7d9ae587e22dd26e2e04304efea9ccbb8 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 18:59:06 +0100 Subject: [PATCH 39/46] Add warning when failing to create transparent window --- crates/eframe/src/native/glow_integration.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index bf7421a89c6..c3749a94718 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -8,6 +8,7 @@ use std::{cell::RefCell, rc::Rc, sync::Arc, time::Instant}; use glutin::{ + config::GlConfig, context::NotCurrentGlContext, display::GetGlDisplay, prelude::{GlDisplay, PossiblyCurrentGlContext}, @@ -977,11 +978,16 @@ impl GlutinWindowContext { window } else { log::debug!("Creating a window for viewport {viewport_id:?}"); - let window = glutin_winit::finalize_window( - event_loop, - create_winit_window_builder(&self.egui_ctx, event_loop, viewport.builder.clone()), - &self.gl_config, - )?; + let window_builder = + create_winit_window_builder(&self.egui_ctx, event_loop, viewport.builder.clone()); + + if window_builder.transparent() && self.gl_config.supports_transparency() == Some(false) + { + log::error!("Cannot create transparent window: the GL config does not support it"); + } + + let window = + glutin_winit::finalize_window(event_loop, window_builder, &self.gl_config)?; apply_viewport_builder_to_new_window(&window, &viewport.builder); viewport.info.minimized = window.is_minimized(); viewport.info.maximized = Some(window.is_maximized()); From 58a96210cf505bf78bf8caaabdec60689dc3cfb3 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 19:22:43 +0100 Subject: [PATCH 40/46] Add `Key::from_name` helper --- crates/eframe/src/web/input.rs | 86 +------------- crates/egui-winit/src/lib.rs | 51 +-------- crates/egui/src/data/input.rs | 200 ++++++++++++++++++++++++++++++++- 3 files changed, 197 insertions(+), 140 deletions(-) diff --git a/crates/eframe/src/web/input.rs b/crates/eframe/src/web/input.rs index 33ea30b6dce..96cad32e20f 100644 --- a/crates/eframe/src/web/input.rs +++ b/crates/eframe/src/web/input.rs @@ -112,91 +112,7 @@ pub fn should_ignore_key(key: &str) -> bool { /// Web sends all keys as strings, so it is up to us to figure out if it is /// a real text input or the name of a key. pub fn translate_key(key: &str) -> Option { - use egui::Key; - - match key { - "ArrowDown" => Some(Key::ArrowDown), - "ArrowLeft" => Some(Key::ArrowLeft), - "ArrowRight" => Some(Key::ArrowRight), - "ArrowUp" => Some(Key::ArrowUp), - - "Esc" | "Escape" => Some(Key::Escape), - "Tab" => Some(Key::Tab), - "Backspace" => Some(Key::Backspace), - "Enter" => Some(Key::Enter), - "Space" | " " => Some(Key::Space), - - "Help" | "Insert" => Some(Key::Insert), - "Delete" => Some(Key::Delete), - "Home" => Some(Key::Home), - "End" => Some(Key::End), - "PageUp" => Some(Key::PageUp), - "PageDown" => Some(Key::PageDown), - - "-" => Some(Key::Minus), - "+" | "=" => Some(Key::PlusEquals), - - "0" => Some(Key::Num0), - "1" => Some(Key::Num1), - "2" => Some(Key::Num2), - "3" => Some(Key::Num3), - "4" => Some(Key::Num4), - "5" => Some(Key::Num5), - "6" => Some(Key::Num6), - "7" => Some(Key::Num7), - "8" => Some(Key::Num8), - "9" => Some(Key::Num9), - - "a" | "A" => Some(Key::A), - "b" | "B" => Some(Key::B), - "c" | "C" => Some(Key::C), - "d" | "D" => Some(Key::D), - "e" | "E" => Some(Key::E), - "f" | "F" => Some(Key::F), - "g" | "G" => Some(Key::G), - "h" | "H" => Some(Key::H), - "i" | "I" => Some(Key::I), - "j" | "J" => Some(Key::J), - "k" | "K" => Some(Key::K), - "l" | "L" => Some(Key::L), - "m" | "M" => Some(Key::M), - "n" | "N" => Some(Key::N), - "o" | "O" => Some(Key::O), - "p" | "P" => Some(Key::P), - "q" | "Q" => Some(Key::Q), - "r" | "R" => Some(Key::R), - "s" | "S" => Some(Key::S), - "t" | "T" => Some(Key::T), - "u" | "U" => Some(Key::U), - "v" | "V" => Some(Key::V), - "w" | "W" => Some(Key::W), - "x" | "X" => Some(Key::X), - "y" | "Y" => Some(Key::Y), - "z" | "Z" => Some(Key::Z), - - "F1" => Some(Key::F1), - "F2" => Some(Key::F2), - "F3" => Some(Key::F3), - "F4" => Some(Key::F4), - "F5" => Some(Key::F5), - "F6" => Some(Key::F6), - "F7" => Some(Key::F7), - "F8" => Some(Key::F8), - "F9" => Some(Key::F9), - "F10" => Some(Key::F10), - "F11" => Some(Key::F11), - "F12" => Some(Key::F12), - "F13" => Some(Key::F13), - "F14" => Some(Key::F14), - "F15" => Some(Key::F15), - "F16" => Some(Key::F16), - "F17" => Some(Key::F17), - "F18" => Some(Key::F18), - "F19" => Some(Key::F19), - "F20" => Some(Key::F20), - - _ => None, - } + egui::Key::from_name(key) } pub fn modifiers_from_event(event: &web_sys::KeyboardEvent) -> egui::Modifiers { diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 218a2f86935..42b876ca031 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -932,7 +932,7 @@ fn translate_mouse_button(button: winit::event::MouseButton) -> Option Option { match key { winit::keyboard::Key::Named(named_key) => key_from_named_key(*named_key), - winit::keyboard::Key::Character(str) => key_from_string(str.as_str()), + winit::keyboard::Key::Character(str) => egui::Key::from_name(str.as_str()), winit::keyboard::Key::Unidentified(_) | winit::keyboard::Key::Dead(_) => None, } } @@ -984,55 +984,6 @@ fn key_from_named_key(named_key: winit::keyboard::NamedKey) -> Option } } -fn key_from_string(as_str: &str) -> Option { - use egui::Key; - - match as_str { - "-" => Some(Key::Minus), - "+" | "=" => Some(Key::PlusEquals), - - "0" => Some(Key::Num0), - "1" => Some(Key::Num1), - "2" => Some(Key::Num2), - "3" => Some(Key::Num3), - "4" => Some(Key::Num4), - "5" => Some(Key::Num5), - "6" => Some(Key::Num6), - "7" => Some(Key::Num7), - "8" => Some(Key::Num8), - "9" => Some(Key::Num9), - - "a" | "A" => Some(Key::A), - "b" | "B" => Some(Key::B), - "c" | "C" => Some(Key::C), - "d" | "D" => Some(Key::D), - "e" | "E" => Some(Key::E), - "f" | "F" => Some(Key::F), - "g" | "G" => Some(Key::G), - "h" | "H" => Some(Key::H), - "i" | "I" => Some(Key::I), - "j" | "J" => Some(Key::J), - "k" | "K" => Some(Key::K), - "l" | "L" => Some(Key::L), - "m" | "M" => Some(Key::M), - "n" | "N" => Some(Key::N), - "o" | "O" => Some(Key::O), - "p" | "P" => Some(Key::P), - "q" | "Q" => Some(Key::Q), - "r" | "R" => Some(Key::R), - "s" | "S" => Some(Key::S), - "t" | "T" => Some(Key::T), - "u" | "U" => Some(Key::U), - "v" | "V" => Some(Key::V), - "w" | "W" => Some(Key::W), - "x" | "X" => Some(Key::X), - "y" | "Y" => Some(Key::Y), - "z" | "Z" => Some(Key::Z), - - _ => None, - } -} - fn key_from_key_code(key: winit::keyboard::KeyCode) -> Option { use egui::Key; use winit::keyboard::KeyCode; diff --git a/crates/egui/src/data/input.rs b/crates/egui/src/data/input.rs index 0609b38d636..559544f0dee 100644 --- a/crates/egui/src/data/input.rs +++ b/crates/egui/src/data/input.rs @@ -865,11 +865,8 @@ impl<'a> ModifierNames<'a> { /// Keyboard keys. /// -/// Includes all keys egui is interested in (such as `Home` and `End`) -/// plus a few that are useful for detecting keyboard shortcuts. -/// -/// Many keys are omitted because they are not always physical keys (depending on keyboard language), e.g. `;` and `§`, -/// and are therefore unsuitable as keyboard shortcuts if you want your app to be portable. +/// egui usually uses logical keys, i.e. after applying any user keymap. +// TODO(emilk): split into `LogicalKey` and `PhysicalKey` #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum Key { @@ -978,6 +975,175 @@ pub enum Key { } impl Key { + /// All egui keys + pub const ALL: &'static [Self] = &[ + Self::ArrowDown, + Self::ArrowLeft, + Self::ArrowRight, + Self::ArrowUp, + Self::Escape, + Self::Tab, + Self::Backspace, + Self::Enter, + Self::Space, + Self::Insert, + Self::Delete, + Self::Home, + Self::End, + Self::PageUp, + Self::PageDown, + Self::Minus, + Self::PlusEquals, + Self::Num0, + Self::Num1, + Self::Num2, + Self::Num3, + Self::Num4, + Self::Num5, + Self::Num6, + Self::Num7, + Self::Num8, + Self::Num9, + Self::A, + Self::B, + Self::C, + Self::D, + Self::E, + Self::F, + Self::G, + Self::H, + Self::I, + Self::J, + Self::K, + Self::L, + Self::M, + Self::N, + Self::O, + Self::P, + Self::Q, + Self::R, + Self::S, + Self::T, + Self::U, + Self::V, + Self::W, + Self::X, + Self::Y, + Self::Z, + Self::F1, + Self::F2, + Self::F3, + Self::F4, + Self::F5, + Self::F6, + Self::F7, + Self::F8, + Self::F9, + Self::F10, + Self::F11, + Self::F12, + Self::F13, + Self::F14, + Self::F15, + Self::F16, + Self::F17, + Self::F18, + Self::F19, + Self::F20, + ]; + + /// Converts `"A"` to `Key::A`, `Space` to `Key::Space`, etc. + /// + /// Makes sense for logical keys. + /// + /// This will parse the output of both [`Self::name`] and [`Self::symbol_or_name`], + /// but will also parse single characters, so that both `"-"` and `"Minus"` will return `Key::Minus`. + pub fn from_name(key: &str) -> Option { + match key { + "Down" | "ArrowDown" | "⏷" => Some(Self::ArrowDown), + "Left" | "ArrowLeft" | "⏴" => Some(Self::ArrowLeft), + "Right" | "ArrowRight" | "⏵" => Some(Self::ArrowRight), + "Up" | "ArrowUp" | "⏶" => Some(Self::ArrowUp), + + "Esc" | "Escape" => Some(Self::Escape), + "Tab" => Some(Self::Tab), + "Backspace" => Some(Self::Backspace), + "Enter" | "Return" => Some(Self::Enter), + "Space" | " " => Some(Self::Space), + + "Help" | "Insert" => Some(Self::Insert), + "Delete" => Some(Self::Delete), + "Home" => Some(Self::Home), + "End" => Some(Self::End), + "PageUp" => Some(Self::PageUp), + "PageDown" => Some(Self::PageDown), + + "Minus" | "-" | "−" => Some(Self::Minus), + "Plus" | "+" | "Equals" | "=" => Some(Self::PlusEquals), + + "0" => Some(Self::Num0), + "1" => Some(Self::Num1), + "2" => Some(Self::Num2), + "3" => Some(Self::Num3), + "4" => Some(Self::Num4), + "5" => Some(Self::Num5), + "6" => Some(Self::Num6), + "7" => Some(Self::Num7), + "8" => Some(Self::Num8), + "9" => Some(Self::Num9), + + "a" | "A" => Some(Self::A), + "b" | "B" => Some(Self::B), + "c" | "C" => Some(Self::C), + "d" | "D" => Some(Self::D), + "e" | "E" => Some(Self::E), + "f" | "F" => Some(Self::F), + "g" | "G" => Some(Self::G), + "h" | "H" => Some(Self::H), + "i" | "I" => Some(Self::I), + "j" | "J" => Some(Self::J), + "k" | "K" => Some(Self::K), + "l" | "L" => Some(Self::L), + "m" | "M" => Some(Self::M), + "n" | "N" => Some(Self::N), + "o" | "O" => Some(Self::O), + "p" | "P" => Some(Self::P), + "q" | "Q" => Some(Self::Q), + "r" | "R" => Some(Self::R), + "s" | "S" => Some(Self::S), + "t" | "T" => Some(Self::T), + "u" | "U" => Some(Self::U), + "v" | "V" => Some(Self::V), + "w" | "W" => Some(Self::W), + "x" | "X" => Some(Self::X), + "y" | "Y" => Some(Self::Y), + "z" | "Z" => Some(Self::Z), + + "F1" => Some(Self::F1), + "F2" => Some(Self::F2), + "F3" => Some(Self::F3), + "F4" => Some(Self::F4), + "F5" => Some(Self::F5), + "F6" => Some(Self::F6), + "F7" => Some(Self::F7), + "F8" => Some(Self::F8), + "F9" => Some(Self::F9), + "F10" => Some(Self::F10), + "F11" => Some(Self::F11), + "F12" => Some(Self::F12), + "F13" => Some(Self::F13), + "F14" => Some(Self::F14), + "F15" => Some(Self::F15), + "F16" => Some(Self::F16), + "F17" => Some(Self::F17), + "F18" => Some(Self::F18), + "F19" => Some(Self::F19), + "F20" => Some(Self::F20), + + _ => None, + } + } + /// Emoji or name representing the key pub fn symbol_or_name(self) -> &'static str { // TODO(emilk): add support for more unicode symbols (see for instance https://wincent.com/wiki/Unicode_representations_of_modifier_keys). @@ -1001,19 +1167,23 @@ impl Key { Key::ArrowLeft => "Left", Key::ArrowRight => "Right", Key::ArrowUp => "Up", + Key::Escape => "Escape", Key::Tab => "Tab", Key::Backspace => "Backspace", Key::Enter => "Enter", Key::Space => "Space", + Key::Insert => "Insert", Key::Delete => "Delete", Key::Home => "Home", Key::End => "End", Key::PageUp => "PageUp", Key::PageDown => "PageDown", + Key::Minus => "Minus", Key::PlusEquals => "Plus", + Key::Num0 => "0", Key::Num1 => "1", Key::Num2 => "2", @@ -1024,6 +1194,7 @@ impl Key { Key::Num7 => "7", Key::Num8 => "8", Key::Num9 => "9", + Key::A => "A", Key::B => "B", Key::C => "C", @@ -1074,6 +1245,25 @@ impl Key { } } +#[test] +fn test_key_from_name() { + for &key in Key::ALL { + let name = key.name(); + assert_eq!( + Key::from_name(name), + Some(key), + "Failed to roundtrip {key:?} from name {name:?}" + ); + + let symbol = key.symbol_or_name(); + assert_eq!( + Key::from_name(symbol), + Some(key), + "Failed to roundtrip {key:?} from symbol {symbol:?}" + ); + } +} + // ---------------------------------------------------------------------------- /// A keyboard shortcut, e.g. `Ctrl+Alt+W`. From edaf2a32188eff7092b87c81e1799494e383540c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 19:36:11 +0100 Subject: [PATCH 41/46] Add keys: period, comma, colon, semicolon --- crates/egui-winit/src/lib.rs | 5 + crates/egui/src/data/input.rs | 216 ++++++++++++++++++++-------------- 2 files changed, 135 insertions(+), 86 deletions(-) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 42b876ca031..b409ff893ec 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -1007,6 +1007,11 @@ fn key_from_key_code(key: winit::keyboard::KeyCode) -> Option { KeyCode::PageUp => Key::PageUp, KeyCode::PageDown => Key::PageDown, + KeyCode::Comma => Key::Comma, + KeyCode::Period => Key::Period, + // KeyCode::Colon => Key::Colon, // NOTE: there is no physical colon key on an american keyboard + KeyCode::Semicolon => Key::Semicolon, + KeyCode::Minus | KeyCode::NumpadSubtract => Key::Minus, // Using Mac the key with the Plus sign on it is reported as the Equals key diff --git a/crates/egui/src/data/input.rs b/crates/egui/src/data/input.rs index 559544f0dee..6f22243f954 100644 --- a/crates/egui/src/data/input.rs +++ b/crates/egui/src/data/input.rs @@ -888,12 +888,28 @@ pub enum Key { PageUp, PageDown, - /// The virtual keycode for the Minus key. + // ---------------------------------------------- + // Punctuation: + /// `:` + Colon, + + /// `,` + Comma, + + /// `-` Minus, - /// The virtual keycode for the Plus/Equals key. + /// `.` + Period, + + /// The for the Plus/Equals key. PlusEquals, + /// `;` + Semicolon, + + // ---------------------------------------------- + // Digits: /// Either from the main row or from the numpad. Num0, @@ -924,6 +940,8 @@ pub enum Key { /// Either from the main row or from the numpad. Num9, + // ---------------------------------------------- + // Letters: A, // Used for cmd+A (select All) B, C, // |CMD COPY| @@ -951,7 +969,8 @@ pub enum Key { Y, Z, // |CMD UNDO| - // The function keys: + // ---------------------------------------------- + // Function keys: F1, F2, F3, @@ -972,6 +991,9 @@ pub enum Key { F18, F19, F20, + // When adding keys, remember to also update `crates/egui-winit/src/lib.rs` + // and [`Self::ALL`]. + // Also: don't add keys last; add them to the group they best belong to. } impl Key { @@ -992,8 +1014,14 @@ impl Key { Self::End, Self::PageUp, Self::PageDown, + // Punctuation: + Self::Colon, + Self::Comma, Self::Minus, + Self::Period, Self::PlusEquals, + Self::Semicolon, + // Digits: Self::Num0, Self::Num1, Self::Num2, @@ -1004,6 +1032,7 @@ impl Key { Self::Num7, Self::Num8, Self::Num9, + // Letters: Self::A, Self::B, Self::C, @@ -1030,6 +1059,7 @@ impl Key { Self::X, Self::Y, Self::Z, + // Function keys: Self::F1, Self::F2, Self::F3, @@ -1059,89 +1089,93 @@ impl Key { /// This will parse the output of both [`Self::name`] and [`Self::symbol_or_name`], /// but will also parse single characters, so that both `"-"` and `"Minus"` will return `Key::Minus`. pub fn from_name(key: &str) -> Option { - match key { - "Down" | "ArrowDown" | "⏷" => Some(Self::ArrowDown), - "Left" | "ArrowLeft" | "⏴" => Some(Self::ArrowLeft), - "Right" | "ArrowRight" | "⏵" => Some(Self::ArrowRight), - "Up" | "ArrowUp" | "⏶" => Some(Self::ArrowUp), - - "Esc" | "Escape" => Some(Self::Escape), - "Tab" => Some(Self::Tab), - "Backspace" => Some(Self::Backspace), - "Enter" | "Return" => Some(Self::Enter), - "Space" | " " => Some(Self::Space), - - "Help" | "Insert" => Some(Self::Insert), - "Delete" => Some(Self::Delete), - "Home" => Some(Self::Home), - "End" => Some(Self::End), - "PageUp" => Some(Self::PageUp), - "PageDown" => Some(Self::PageDown), - - "Minus" | "-" | "−" => Some(Self::Minus), - "Plus" | "+" | "Equals" | "=" => Some(Self::PlusEquals), - - "0" => Some(Self::Num0), - "1" => Some(Self::Num1), - "2" => Some(Self::Num2), - "3" => Some(Self::Num3), - "4" => Some(Self::Num4), - "5" => Some(Self::Num5), - "6" => Some(Self::Num6), - "7" => Some(Self::Num7), - "8" => Some(Self::Num8), - "9" => Some(Self::Num9), - - "a" | "A" => Some(Self::A), - "b" | "B" => Some(Self::B), - "c" | "C" => Some(Self::C), - "d" | "D" => Some(Self::D), - "e" | "E" => Some(Self::E), - "f" | "F" => Some(Self::F), - "g" | "G" => Some(Self::G), - "h" | "H" => Some(Self::H), - "i" | "I" => Some(Self::I), - "j" | "J" => Some(Self::J), - "k" | "K" => Some(Self::K), - "l" | "L" => Some(Self::L), - "m" | "M" => Some(Self::M), - "n" | "N" => Some(Self::N), - "o" | "O" => Some(Self::O), - "p" | "P" => Some(Self::P), - "q" | "Q" => Some(Self::Q), - "r" | "R" => Some(Self::R), - "s" | "S" => Some(Self::S), - "t" | "T" => Some(Self::T), - "u" | "U" => Some(Self::U), - "v" | "V" => Some(Self::V), - "w" | "W" => Some(Self::W), - "x" | "X" => Some(Self::X), - "y" | "Y" => Some(Self::Y), - "z" | "Z" => Some(Self::Z), - - "F1" => Some(Self::F1), - "F2" => Some(Self::F2), - "F3" => Some(Self::F3), - "F4" => Some(Self::F4), - "F5" => Some(Self::F5), - "F6" => Some(Self::F6), - "F7" => Some(Self::F7), - "F8" => Some(Self::F8), - "F9" => Some(Self::F9), - "F10" => Some(Self::F10), - "F11" => Some(Self::F11), - "F12" => Some(Self::F12), - "F13" => Some(Self::F13), - "F14" => Some(Self::F14), - "F15" => Some(Self::F15), - "F16" => Some(Self::F16), - "F17" => Some(Self::F17), - "F18" => Some(Self::F18), - "F19" => Some(Self::F19), - "F20" => Some(Self::F20), - - _ => None, - } + Some(match key { + "ArrowDown" | "Down" | "⏷" => Self::ArrowDown, + "ArrowLeft" | "Left" | "⏴" => Self::ArrowLeft, + "ArrowRight" | "Right" | "⏵" => Self::ArrowRight, + "ArrowUp" | "Up" | "⏶" => Self::ArrowUp, + + "Escape" | "Esc" => Self::Escape, + "Tab" => Self::Tab, + "Backspace" => Self::Backspace, + "Enter" | "Return" => Self::Enter, + "Space" | " " => Self::Space, + + "Help" | "Insert" => Self::Insert, + "Delete" => Self::Delete, + "Home" => Self::Home, + "End" => Self::End, + "PageUp" => Self::PageUp, + "PageDown" => Self::PageDown, + + "Colon" | ":" => Self::Colon, + "Comma" | "," => Self::Comma, + "Minus" | "-" | "−" => Self::Minus, + "Period" | "." => Self::Period, + "Plus" | "+" | "Equals" | "=" => Self::PlusEquals, + "Semicolon" | ";" => Self::Semicolon, + + "0" => Self::Num0, + "1" => Self::Num1, + "2" => Self::Num2, + "3" => Self::Num3, + "4" => Self::Num4, + "5" => Self::Num5, + "6" => Self::Num6, + "7" => Self::Num7, + "8" => Self::Num8, + "9" => Self::Num9, + + "a" | "A" => Self::A, + "b" | "B" => Self::B, + "c" | "C" => Self::C, + "d" | "D" => Self::D, + "e" | "E" => Self::E, + "f" | "F" => Self::F, + "g" | "G" => Self::G, + "h" | "H" => Self::H, + "i" | "I" => Self::I, + "j" | "J" => Self::J, + "k" | "K" => Self::K, + "l" | "L" => Self::L, + "m" | "M" => Self::M, + "n" | "N" => Self::N, + "o" | "O" => Self::O, + "p" | "P" => Self::P, + "q" | "Q" => Self::Q, + "r" | "R" => Self::R, + "s" | "S" => Self::S, + "t" | "T" => Self::T, + "u" | "U" => Self::U, + "v" | "V" => Self::V, + "w" | "W" => Self::W, + "x" | "X" => Self::X, + "y" | "Y" => Self::Y, + "z" | "Z" => Self::Z, + + "F1" => Self::F1, + "F2" => Self::F2, + "F3" => Self::F3, + "F4" => Self::F4, + "F5" => Self::F5, + "F6" => Self::F6, + "F7" => Self::F7, + "F8" => Self::F8, + "F9" => Self::F9, + "F10" => Self::F10, + "F11" => Self::F11, + "F12" => Self::F12, + "F13" => Self::F13, + "F14" => Self::F14, + "F15" => Self::F15, + "F16" => Self::F16, + "F17" => Self::F17, + "F18" => Self::F18, + "F19" => Self::F19, + "F20" => Self::F20, + + _ => return None, + }) } /// Emoji or name representing the key @@ -1181,8 +1215,12 @@ impl Key { Key::PageUp => "PageUp", Key::PageDown => "PageDown", + Key::Colon => "Colon", + Key::Comma => "Comma", Key::Minus => "Minus", + Key::Period => "Period", Key::PlusEquals => "Plus", + Key::Semicolon => "Semicolon", Key::Num0 => "0", Key::Num1 => "1", @@ -1247,6 +1285,12 @@ impl Key { #[test] fn test_key_from_name() { + assert_eq!( + Key::ALL.len(), + Key::F20 as usize + 1, + "Some keys are missing in Key::ALL" + ); + for &key in Key::ALL { let name = key.name(); assert_eq!( From 70ed053060cb172d6b14279b398752e129506122 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Nov 2023 19:49:32 +0100 Subject: [PATCH 42/46] Improve docstring --- crates/egui/src/data/input.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/egui/src/data/input.rs b/crates/egui/src/data/input.rs index 6f22243f954..c22450f5f69 100644 --- a/crates/egui/src/data/input.rs +++ b/crates/egui/src/data/input.rs @@ -1088,6 +1088,9 @@ impl Key { /// /// This will parse the output of both [`Self::name`] and [`Self::symbol_or_name`], /// but will also parse single characters, so that both `"-"` and `"Minus"` will return `Key::Minus`. + /// + /// This should support both the names generated in a web browser, + /// and by winit. Please test on both with `eframe`. pub fn from_name(key: &str) -> Option { Some(match key { "ArrowDown" | "Down" | "⏷" => Self::ArrowDown, From a624f744a7dcdd7b48f0a62b844a02949664a067 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 30 Nov 2023 08:42:38 +0100 Subject: [PATCH 43/46] Ignore text on key release and when ctrl is down --- crates/egui-winit/src/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index b409ff893ec..55160a667a9 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -704,10 +704,14 @@ impl State { } if let Some(text) = &text { - // On Mac we get here when the user presses Cmd-C (copy), ctrl-W, etc. + // On some platforms we get here when the user presses Cmd-C (copy), ctrl-W, etc. // We need to ignore these characters that are side-effects of commands. - let is_mac_cmd = cfg!(target_os = "macos") && self.egui_input.modifiers.mac_cmd; - if !is_mac_cmd { + // Also make sure the key is pressed (not released). On Linux, text might + // contain some data even when the key is released. + let is_cmd = self.egui_input.modifiers.ctrl + || self.egui_input.modifiers.command + || self.egui_input.modifiers.mac_cmd; + if pressed && !is_cmd { self.egui_input .events .push(egui::Event::Text(text.to_string())); From d076bdc0389aab7da9a404dc3efd4c9e57f90fc3 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 1 Dec 2023 15:54:51 +0100 Subject: [PATCH 44/46] Only register printable text --- crates/egui-winit/src/lib.rs | 38 +++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index c189e805c52..0ad825a073c 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -715,17 +715,21 @@ impl State { } if let Some(text) = &text { - // On some platforms we get here when the user presses Cmd-C (copy), ctrl-W, etc. - // We need to ignore these characters that are side-effects of commands. - // Also make sure the key is pressed (not released). On Linux, text might - // contain some data even when the key is released. - let is_cmd = self.egui_input.modifiers.ctrl - || self.egui_input.modifiers.command - || self.egui_input.modifiers.mac_cmd; - if pressed && !is_cmd { - self.egui_input - .events - .push(egui::Event::Text(text.to_string())); + // Make sure there is text, and that it is not control characters + // (e.g. delete is sent as "\u{f728}" on macOS). + if !text.is_empty() && text.chars().all(is_printable_char) { + // On some platforms we get here when the user presses Cmd-C (copy), ctrl-W, etc. + // We need to ignore these characters that are side-effects of commands. + // Also make sure the key is pressed (not released). On Linux, text might + // contain some data even when the key is released. + let is_cmd = self.egui_input.modifiers.ctrl + || self.egui_input.modifiers.command + || self.egui_input.modifiers.mac_cmd; + if pressed && !is_cmd { + self.egui_input + .events + .push(egui::Event::Text(text.to_string())); + } } } @@ -929,6 +933,18 @@ fn open_url_in_browser(_url: &str) { } } +/// Winit sends special keys (backspace, delete, F1, …) as characters. +/// Ignore those. +/// We also ignore '\r', '\n', '\t'. +/// Newlines are handled by the `Key::Enter` event. +fn is_printable_char(chr: char) -> bool { + let is_in_private_use_area = '\u{e000}' <= chr && chr <= '\u{f8ff}' + || '\u{f0000}' <= chr && chr <= '\u{ffffd}' + || '\u{100000}' <= chr && chr <= '\u{10fffd}'; + + !is_in_private_use_area && !chr.is_ascii_control() +} + fn is_cut_command(modifiers: egui::Modifiers, keycode: egui::Key) -> bool { (modifiers.command && keycode == egui::Key::X) || (cfg!(target_os = "windows") && modifiers.shift && keycode == egui::Key::Delete) From a13959ac77b93492fa38c5a33c169cb462da4e4f Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 6 Dec 2023 13:27:29 +0100 Subject: [PATCH 45/46] Fix modifiers on Linux --- crates/egui-winit/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index a2adca45c69..da4d2bc4358 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -388,12 +388,12 @@ impl State { } } WindowEvent::ModifiersChanged(state) => { - use winit::keyboard::ModifiersKeyState::Pressed; + let state = state.state(); - let alt = state.lalt_state() == Pressed || state.ralt_state() == Pressed; - let ctrl = state.lcontrol_state() == Pressed || state.rcontrol_state() == Pressed; - let shift = state.lshift_state() == Pressed || state.rshift_state() == Pressed; - let super_ = state.lsuper_state() == Pressed || state.rsuper_state() == Pressed; + let alt = state.alt_key(); + let ctrl = state.control_key(); + let shift = state.shift_key(); + let super_ = state.super_key(); self.egui_input.modifiers.alt = alt; self.egui_input.modifiers.ctrl = ctrl; From d63deb72b3015ee42109ff0e193ffb4134a901bf Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 18 Dec 2023 10:03:10 +0100 Subject: [PATCH 46/46] Update deny.toml --- deny.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deny.toml b/deny.toml index f4d27013d61..6882337c630 100644 --- a/deny.toml +++ b/deny.toml @@ -37,10 +37,11 @@ skip = [ { name = "arrayvec" }, # old version via tiny-skiaz { name = "base64" }, # small crate, old version from usvg { name = "bitflags" }, # old 1.0 version via glutin, png, spirv, … - { name = "glow" }, # TODO(@wumpf): Old version use for glow backend right now, newer for wgpu. Updating this trickles out to updating winit. - { name = "glutin_wgl_sys" }, # TODO(@wumpf): Old version use for glow backend right now, newer for wgpu. Updating this trickles out to updating winit. + { name = "glow" }, # TODO(@wumpf): updatere glow + { name = "glutin_wgl_sys" }, # TODO(@wumpf): updatere glow { name = "libloading" }, # wgpu-hal itself depends on 0.8 while some of its dependencies, like ash and d3d12, depend on 0.7 { name = "memoffset" }, # tiny dependency + { name = "quick-xml" }, # old version via wayland-scanner { name = "redox_syscall" }, # old version via directories-next { name = "spin" }, # old version via ring through rusttls and other libraries, newer for wgpu. { name = "time" }, # old version pulled in by unmaintianed crate 'chrono'