1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 14:49:06 -04:00

Get hello world simple to compile

This commit is contained in:
lucasmerlin
2025-11-19 12:14:08 +01:00
parent 7980401b25
commit e285050abc
25 changed files with 1016 additions and 766 deletions

View File

@@ -109,7 +109,7 @@ dependencies = [
"accesskit_unix",
"accesskit_windows",
"raw-window-handle",
"winit",
"winit 0.30.12",
]
[[package]]
@@ -647,6 +647,15 @@ dependencies = [
"piper",
]
[[package]]
name = "borsh"
version = "1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce"
dependencies = [
"cfg_aliases",
]
[[package]]
name = "bstr"
version = "1.11.3"
@@ -716,18 +725,43 @@ dependencies = [
"thiserror 1.0.66",
]
[[package]]
name = "calloop"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e"
dependencies = [
"bitflags 2.9.4",
"polling",
"rustix 1.0.8",
"slab",
"tracing",
]
[[package]]
name = "calloop-wayland-source"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20"
dependencies = [
"calloop",
"calloop 0.13.0",
"rustix 0.38.38",
"wayland-backend",
"wayland-client",
]
[[package]]
name = "calloop-wayland-source"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa"
dependencies = [
"calloop 0.14.3",
"rustix 1.0.8",
"wayland-backend",
"wayland-client",
]
[[package]]
name = "cast"
version = "0.3.0"
@@ -1082,9 +1116,12 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "cursor-icon"
version = "1.1.0"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
dependencies = [
"serde",
]
[[package]]
name = "custom_3d_glow"
@@ -1242,9 +1279,9 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
[[package]]
name = "dpi"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53"
checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
[[package]]
name = "ecolor"
@@ -1294,7 +1331,8 @@ dependencies = [
"web-time",
"wgpu",
"windows-sys 0.61.2",
"winit",
"winit 0.31.0-beta.2",
"winit-core",
]
[[package]]
@@ -1305,6 +1343,7 @@ dependencies = [
"ahash",
"backtrace",
"bitflags 2.9.4",
"cursor-icon",
"document-features",
"emath",
"epaint",
@@ -1332,7 +1371,7 @@ dependencies = [
"type-map",
"web-time",
"wgpu",
"winit",
"winit 0.31.0-beta.2",
]
[[package]]
@@ -1343,11 +1382,12 @@ dependencies = [
"arboard",
"bytemuck",
"document-features",
"dpi",
"egui",
"log",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2-ui-kit",
"objc2-ui-kit 0.2.2",
"profiling",
"raw-window-handle",
"serde",
@@ -1355,7 +1395,8 @@ dependencies = [
"wayland-cursor",
"web-time",
"webbrowser",
"winit",
"winit 0.31.0-beta.2",
"winit-core",
]
[[package]]
@@ -1440,7 +1481,7 @@ dependencies = [
"profiling",
"wasm-bindgen",
"web-sys",
"winit",
"winit 0.31.0-beta.2",
]
[[package]]
@@ -1664,7 +1705,7 @@ version = "0.1.0"
dependencies = [
"eframe",
"env_logger",
"winit",
"winit 0.31.0-beta.2",
]
[[package]]
@@ -1675,7 +1716,7 @@ dependencies = [
"env_logger",
"log",
"tokio",
"winit",
"winit 0.31.0-beta.2",
]
[[package]]
@@ -1987,7 +2028,7 @@ dependencies = [
"cfg_aliases",
"glutin",
"raw-window-handle",
"winit",
"winit 0.30.12",
]
[[package]]
@@ -2108,7 +2149,7 @@ dependencies = [
"egui_demo_lib",
"egui_extras",
"log",
"winit",
"winit 0.31.0-beta.2",
]
[[package]]
@@ -2126,7 +2167,7 @@ version = "0.1.0"
dependencies = [
"eframe",
"env_logger",
"winit",
"winit 0.31.0-beta.2",
]
[[package]]
@@ -2480,6 +2521,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "keyboard-types"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fbe853b403ae61a04233030ae8a79d94975281ed9770a1f9e246732b534b28d"
dependencies = [
"bitflags 2.9.4",
"serde",
]
[[package]]
name = "keyboard_events"
version = "0.1.0"
@@ -2955,6 +3006,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
"bitflags 2.9.4",
"block2 0.6.2",
"dispatch2",
"objc2 0.6.3",
]
@@ -2967,6 +3019,7 @@ checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
dependencies = [
"bitflags 2.9.4",
"dispatch2",
"libc",
"objc2 0.6.3",
"objc2-core-foundation",
"objc2-io-surface",
@@ -2996,6 +3049,17 @@ dependencies = [
"objc2-foundation 0.2.2",
]
[[package]]
name = "objc2-core-video"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6"
dependencies = [
"bitflags 2.9.4",
"objc2-core-foundation",
"objc2-core-graphics",
]
[[package]]
name = "objc2-encode"
version = "4.1.0"
@@ -3022,6 +3086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [
"bitflags 2.9.4",
"block2 0.6.2",
"objc2 0.6.3",
"objc2-core-foundation",
]
@@ -3105,6 +3170,18 @@ dependencies = [
"objc2-user-notifications",
]
[[package]]
name = "objc2-ui-kit"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.3",
"objc2-core-foundation",
"objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-uniform-type-identifiers"
version = "0.2.2"
@@ -3972,14 +4049,14 @@ dependencies = [
[[package]]
name = "sctk-adwaita"
version = "0.10.1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec"
checksum = "1dd3accc0f3f4bbaf2c9e1957a030dc582028130c67660d44c0a0345a22ca69b"
dependencies = [
"ab_glyph",
"log",
"memmap2",
"smithay-client-toolkit",
"smithay-client-toolkit 0.20.0",
"tiny-skia",
]
@@ -4132,8 +4209,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016"
dependencies = [
"bitflags 2.9.4",
"calloop",
"calloop-wayland-source",
"calloop 0.13.0",
"calloop-wayland-source 0.3.0",
"cursor-icon",
"libc",
"log",
@@ -4150,6 +4227,33 @@ dependencies = [
"xkeysym",
]
[[package]]
name = "smithay-client-toolkit"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0"
dependencies = [
"bitflags 2.9.4",
"calloop 0.14.3",
"calloop-wayland-source 0.4.1",
"cursor-icon",
"libc",
"log",
"memmap2",
"rustix 1.0.8",
"thiserror 2.0.17",
"wayland-backend",
"wayland-client",
"wayland-csd-frame",
"wayland-cursor",
"wayland-protocols",
"wayland-protocols-experimental",
"wayland-protocols-misc",
"wayland-protocols-wlr",
"wayland-scanner",
"xkeysym",
]
[[package]]
name = "smithay-clipboard"
version = "0.7.2"
@@ -4157,7 +4261,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846"
dependencies = [
"libc",
"smithay-client-toolkit",
"smithay-client-toolkit 0.19.2",
"wayland-backend",
]
@@ -4170,6 +4274,16 @@ dependencies = [
"serde",
]
[[package]]
name = "smol_str"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9676b89cd56310a87b93dec47b11af744f34d5fc9f367b829474eec0a891350d"
dependencies = [
"borsh",
"serde",
]
[[package]]
name = "socket2"
version = "0.6.0"
@@ -4514,6 +4628,7 @@ version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@@ -4897,6 +5012,32 @@ dependencies = [
"wayland-scanner",
]
[[package]]
name = "wayland-protocols-experimental"
version = "20250721.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1"
dependencies = [
"bitflags 2.9.4",
"wayland-backend",
"wayland-client",
"wayland-protocols",
"wayland-scanner",
]
[[package]]
name = "wayland-protocols-misc"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfe33d551eb8bffd03ff067a8b44bb963919157841a99957151299a6307d19c"
dependencies = [
"bitflags 2.9.4",
"wayland-backend",
"wayland-client",
"wayland-protocols",
"wayland-scanner",
]
[[package]]
name = "wayland-protocols-plasma"
version = "0.3.9"
@@ -5603,7 +5744,7 @@ dependencies = [
"bitflags 2.9.4",
"block2 0.5.1",
"bytemuck",
"calloop",
"calloop 0.13.0",
"cfg_aliases",
"concurrent-queue",
"core-foundation 0.9.4",
@@ -5617,16 +5758,15 @@ dependencies = [
"objc2 0.5.2",
"objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
"objc2-ui-kit",
"objc2-ui-kit 0.2.2",
"orbclient",
"percent-encoding",
"pin-project",
"raw-window-handle",
"redox_syscall 0.4.1",
"rustix 0.38.38",
"sctk-adwaita",
"smithay-client-toolkit",
"smol_str",
"smithay-client-toolkit 0.19.2",
"smol_str 0.2.2",
"tracing",
"unicode-segmentation",
"wasm-bindgen",
@@ -5643,6 +5783,231 @@ dependencies = [
"xkbcommon-dl",
]
[[package]]
name = "winit"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2879d2854d1a43e48f67322d4bd097afcb6eb8f8f775c8de0260a71aea1df1aa"
dependencies = [
"bitflags 2.9.4",
"cfg_aliases",
"cursor-icon",
"dpi",
"libc",
"raw-window-handle",
"rustix 1.0.8",
"smol_str 0.3.2",
"tracing",
"winit-android",
"winit-appkit",
"winit-common",
"winit-core",
"winit-orbital",
"winit-uikit",
"winit-wayland",
"winit-web",
"winit-win32",
"winit-x11",
]
[[package]]
name = "winit-android"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d9c0d2cd93efec3a9f9ad819cfaf0834782403af7c0d248c784ec0c61761df"
dependencies = [
"android-activity",
"bitflags 2.9.4",
"dpi",
"ndk",
"raw-window-handle",
"smol_str 0.3.2",
"tracing",
"winit-core",
]
[[package]]
name = "winit-appkit"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21310ca07851a49c348e0c2cc768e36b52ca65afda2c2354d78ed4b90074d8aa"
dependencies = [
"bitflags 2.9.4",
"block2 0.6.2",
"dispatch2",
"dpi",
"objc2 0.6.3",
"objc2-app-kit 0.3.2",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-core-video",
"objc2-foundation 0.3.2",
"raw-window-handle",
"smol_str 0.3.2",
"tracing",
"winit-common",
"winit-core",
]
[[package]]
name = "winit-common"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45375fbac4cbb77260d83a30b1f9d8105880dbac99a9ae97f56656694680ff69"
dependencies = [
"memmap2",
"objc2 0.6.3",
"objc2-core-foundation",
"smol_str 0.3.2",
"tracing",
"winit-core",
"x11-dl",
"xkbcommon-dl",
]
[[package]]
name = "winit-core"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4f0ccd7abb43740e2c6124ac7cae7d865ecec74eec63783e8922577ac232583"
dependencies = [
"bitflags 2.9.4",
"cursor-icon",
"dpi",
"keyboard-types",
"raw-window-handle",
"smol_str 0.3.2",
"web-time",
]
[[package]]
name = "winit-orbital"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51ea1fb262e7209f265f12bd0cc792c399b14355675e65531e9c8a87db287d46"
dependencies = [
"bitflags 2.9.4",
"dpi",
"orbclient",
"raw-window-handle",
"redox_syscall 0.5.7",
"smol_str 0.3.2",
"tracing",
"winit-core",
]
[[package]]
name = "winit-uikit"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "680a356e798837d8eb274d4556e83bceaf81698194e31aafc5cfb8a9f2fab643"
dependencies = [
"bitflags 2.9.4",
"block2 0.6.2",
"dispatch2",
"dpi",
"objc2 0.6.3",
"objc2-core-foundation",
"objc2-foundation 0.3.2",
"objc2-ui-kit 0.3.2",
"raw-window-handle",
"smol_str 0.3.2",
"tracing",
"winit-common",
"winit-core",
]
[[package]]
name = "winit-wayland"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce5afb2ba07da603f84b722c95f9f9396d2cedae3944fb6c0cda4a6f88de545"
dependencies = [
"ahash",
"bitflags 2.9.4",
"calloop 0.14.3",
"cursor-icon",
"dpi",
"libc",
"memmap2",
"raw-window-handle",
"rustix 1.0.8",
"sctk-adwaita",
"smithay-client-toolkit 0.20.0",
"smol_str 0.3.2",
"tracing",
"wayland-backend",
"wayland-client",
"wayland-protocols",
"wayland-protocols-plasma",
"winit-common",
"winit-core",
]
[[package]]
name = "winit-web"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c2490a953fb776fbbd5e295d54f1c3847f4f15b6c3929ec53c09acda6487a92"
dependencies = [
"atomic-waker",
"bitflags 2.9.4",
"concurrent-queue",
"cursor-icon",
"dpi",
"js-sys",
"pin-project",
"raw-window-handle",
"smol_str 0.3.2",
"tracing",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"web-time",
"winit-core",
]
[[package]]
name = "winit-win32"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "644ea78af0e858aa3b092e5d1c67c41995a98220c81813f1353b28bc8bb91eaa"
dependencies = [
"bitflags 2.9.4",
"cursor-icon",
"dpi",
"raw-window-handle",
"smol_str 0.3.2",
"tracing",
"unicode-segmentation",
"windows-sys 0.59.0",
"winit-core",
]
[[package]]
name = "winit-x11"
version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa5b600756534c7041aa93cd0d244d44b09fca1b89e202bd1cd80dd9f3636c46"
dependencies = [
"bitflags 2.9.4",
"bytemuck",
"calloop 0.14.3",
"cursor-icon",
"dpi",
"libc",
"percent-encoding",
"raw-window-handle",
"rustix 1.0.8",
"smol_str 0.3.2",
"tracing",
"winit-common",
"winit-core",
"x11-dl",
"x11rb",
"xkbcommon-dl",
]
[[package]]
name = "winnow"
version = "0.7.3"
@@ -5691,6 +6056,7 @@ dependencies = [
"once_cell",
"rustix 1.0.8",
"x11rb-protocol",
"xcursor",
]
[[package]]

View File

@@ -85,9 +85,11 @@ chrono = { version = "0.4.42", default-features = false }
cint = "0.3.1"
color-hex = "0.2.0"
criterion = { version = "0.7.0", default-features = false }
cursor-icon = "1"
dify = { version = "0.7.4", default-features = false }
directories = "6.0.0"
document-features = "0.2.11"
dpi = "0.1"
ehttp = { version = "0.5.0", default-features = false }
enum-map = "2.7.3"
env_logger = { version = "0.11.8", default-features = false }
@@ -142,7 +144,8 @@ web-time = "1.1.0" # Timekeeping for native and web
webbrowser = "1.0.5"
wgpu = { version = "27.0.1", default-features = false, features = ["std"] }
windows-sys = "0.61.2"
winit = { version = "0.30.12", default-features = false }
winit = { version = "0.31.0-beta.2", default-features = false }
winit-core = { version = "0.31.0-beta.2", default-features = false }
[workspace.lints.rust]

View File

@@ -140,7 +140,8 @@ serde = { workspace = true, optional = true }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
egui-winit = { workspace = true, default-features = false, features = ["clipboard", "links"] }
image = { workspace = true, features = ["png"] } # Needed for app icon
winit = { workspace = true, default-features = false, features = ["rwh_06"] }
winit = { workspace = true, default-features = false }
winit-core.workspace = true
# optional native:
egui-wgpu = { workspace = true, optional = true, features = [
@@ -169,7 +170,10 @@ objc2-foundation = { workspace = true, default-features = false, features = [
objc2-app-kit = { workspace = true, default-features = false, features = [
"std",
"NSApplication",
"NSBitmapImageRep",
"NSGraphics",
"NSImage",
"NSImageRep",
"NSMenu",
"NSMenuItem",
"NSResponder",

View File

@@ -31,7 +31,7 @@ pub use winit::{event_loop::EventLoopBuilder, window::WindowAttributes};
/// done by `EFrame`.
#[cfg(not(target_arch = "wasm32"))]
#[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))]
pub type EventLoopBuilderHook = Box<dyn FnOnce(&mut EventLoopBuilder<UserEvent>)>;
pub type EventLoopBuilderHook = Box<dyn FnOnce(&mut EventLoopBuilder)>;
/// Hook into the building of a the native window.
///

View File

@@ -327,7 +327,7 @@ pub fn create_native<'a>(
app_name: &str,
mut native_options: NativeOptions,
app_creator: AppCreator<'a>,
event_loop: &winit::event_loop::EventLoop<UserEvent>,
event_loop: &winit::event_loop::EventLoop,
) -> EframeWinitApplication<'a> {
let renderer = init_native(app_name, &mut native_options);
@@ -455,6 +455,10 @@ pub enum Error {
#[cfg(not(target_arch = "wasm32"))]
Winit(winit::error::OsError),
/// An request error from [`winit`].
#[cfg(not(target_arch = "wasm32"))]
WinitRequest(winit::error::RequestError),
/// An error from [`winit::event_loop::EventLoop`].
#[cfg(not(target_arch = "wasm32"))]
WinitEventLoop(winit::error::EventLoopError),
@@ -486,6 +490,14 @@ impl From<winit::error::OsError> for Error {
}
}
#[cfg(not(target_arch = "wasm32"))]
impl From<winit::error::RequestError> for Error {
#[inline]
fn from(err: winit::error::RequestError) -> Self {
Self::WinitRequest(err)
}
}
#[cfg(not(target_arch = "wasm32"))]
impl From<winit::error::EventLoopError> for Error {
#[inline]
@@ -555,6 +567,9 @@ impl std::fmt::Display for Error {
Self::Wgpu(err) => {
write!(f, "WGPU error: {err}")
}
Error::WinitRequest(err) => {
write!(f, "winit request error: {err}")
}
}
}
}

View File

@@ -15,7 +15,7 @@ use crate::epi;
#[cfg_attr(target_os = "ios", allow(dead_code, unused_variables, unused_mut))]
pub fn viewport_builder(
egui_zoom_factor: f32,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
native_options: &mut epi::NativeOptions,
window_settings: Option<WindowSettings>,
) -> ViewportBuilder {
@@ -71,15 +71,16 @@ pub fn viewport_builder(
.primary_monitor()
.or_else(|| event_loop.available_monitors().next())
{
let monitor_size = monitor
.size()
.to_logical::<f32>(egui_zoom_factor as f64 * monitor.scale_factor());
let inner_size = inner_size_points.unwrap_or(egui::Vec2 { x: 800.0, y: 600.0 });
if 0.0 < monitor_size.width && 0.0 < monitor_size.height {
let x = (monitor_size.width - inner_size.x) / 2.0;
let y = (monitor_size.height - inner_size.y) / 2.0;
viewport_builder = viewport_builder.with_position([x, y]);
}
todo!()
// let monitor_size = monitor
// .size()
// .to_logical::<f32>(egui_zoom_factor as f64 * monitor.scale_factor());
// let inner_size = inner_size_points.unwrap_or(egui::Vec2 { x: 800.0, y: 600.0 });
// if 0.0 < monitor_size.width && 0.0 < monitor_size.height {
// let x = (monitor_size.width - inner_size.x) / 2.0;
// let y = (monitor_size.height - inner_size.y) / 2.0;
// viewport_builder = viewport_builder.with_position([x, y]);
// }
}
}
@@ -90,7 +91,7 @@ pub fn viewport_builder(
}
pub fn apply_window_settings(
window: &winit::window::Window,
window: &dyn winit::window::Window,
window_settings: Option<WindowSettings>,
) {
profiling::function_scope!();
@@ -100,7 +101,7 @@ pub fn apply_window_settings(
}
#[cfg(not(target_os = "ios"))]
fn largest_monitor_point_size(egui_zoom_factor: f32, event_loop: &ActiveEventLoop) -> egui::Vec2 {
fn largest_monitor_point_size(egui_zoom_factor: f32, event_loop: &dyn ActiveEventLoop) -> egui::Vec2 {
profiling::function_scope!();
let mut max_size = egui::Vec2::ZERO;
@@ -110,11 +111,12 @@ fn largest_monitor_point_size(egui_zoom_factor: f32, event_loop: &ActiveEventLoo
};
for monitor in available_monitors {
let size = monitor
.size()
.to_logical::<f32>(egui_zoom_factor as f64 * monitor.scale_factor());
let size = egui::vec2(size.width, size.height);
max_size = max_size.max(size);
todo!()
// let size = monitor
// .size()
// .to_logical::<f32>(egui_zoom_factor as f64 * monitor.scale_factor());
// let size = egui::vec2(size.width, size.height);
// max_size = max_size.max(size);
}
if max_size == egui::Vec2::ZERO {
@@ -171,7 +173,7 @@ impl EpiIntegration {
#[allow(clippy::allow_attributes, clippy::too_many_arguments)]
pub fn new(
egui_ctx: egui::Context,
window: &winit::window::Window,
window: &dyn winit::window::Window,
app_name: &str,
native_options: &crate::NativeOptions,
storage: Option<Box<dyn epi::Storage>>,
@@ -233,7 +235,7 @@ impl EpiIntegration {
pub fn on_window_event(
&mut self,
window: &winit::window::Window,
window: &dyn winit::window::Window,
egui_winit: &mut egui_winit::State,
event: &winit::event::WindowEvent,
) -> EventResponse {
@@ -241,14 +243,15 @@ impl EpiIntegration {
use winit::event::{ElementState, MouseButton, WindowEvent};
if let WindowEvent::MouseInput {
button: MouseButton::Left,
state: ElementState::Pressed,
..
} = event
{
self.can_drag_window = true;
}
// TODO
// if let WindowEvent::MouseInput {
// button: MouseButton::Left,
// state: ElementState::Pressed,
// ..
// } = event
// {
// self.can_drag_window = true;
// }
egui_winit.on_window_event(window, event)
}
@@ -304,7 +307,7 @@ impl EpiIntegration {
self.frame.info.cpu_usage = Some(seconds);
}
pub fn post_rendering(&mut self, window: &winit::window::Window) {
pub fn post_rendering(&mut self, window: &dyn winit::window::Window) {
profiling::function_scope!();
if std::mem::take(&mut self.is_first_frame) {
// We keep hidden until we've painted something. See https://github.com/emilk/egui/pull/2279
@@ -318,7 +321,7 @@ impl EpiIntegration {
pub fn maybe_autosave(
&mut self,
app: &mut dyn epi::App,
window: Option<&winit::window::Window>,
window: Option<&dyn winit::window::Window>,
) {
let now = Instant::now();
if now - self.last_auto_save > app.auto_save_interval() {
@@ -327,7 +330,7 @@ impl EpiIntegration {
}
}
pub fn save(&mut self, app: &mut dyn epi::App, window: Option<&winit::window::Window>) {
pub fn save(&mut self, app: &mut dyn epi::App, window: Option<&dyn winit::window::Window>) {
#[cfg(not(feature = "persistence"))]
let _ = (self, app, window);

View File

@@ -2,19 +2,19 @@ use std::cell::Cell;
use winit::event_loop::ActiveEventLoop;
thread_local! {
static CURRENT_EVENT_LOOP: Cell<Option<*const ActiveEventLoop>> = const { Cell::new(None) };
static CURRENT_EVENT_LOOP: Cell<Option<*const dyn ActiveEventLoop>> = const { Cell::new(None) };
}
struct EventLoopGuard;
impl EventLoopGuard {
fn new(event_loop: &ActiveEventLoop) -> Self {
fn new(event_loop: &dyn ActiveEventLoop) -> Self {
CURRENT_EVENT_LOOP.with(|cell| {
assert!(
cell.get().is_none(),
"Attempted to set a new event loop while one is already set"
);
cell.set(Some(std::ptr::from_ref::<ActiveEventLoop>(event_loop)));
cell.set(Some(std::ptr::from_ref::<dyn ActiveEventLoop>(event_loop)));
});
Self
}
@@ -30,7 +30,7 @@ impl Drop for EventLoopGuard {
#[expect(unsafe_code)]
pub fn with_current_event_loop<F, R>(f: F) -> Option<R>
where
F: FnOnce(&ActiveEventLoop) -> R,
F: FnOnce(&dyn ActiveEventLoop) -> R,
{
CURRENT_EVENT_LOOP.with(|cell| {
cell.get().map(|ptr| {
@@ -47,7 +47,7 @@ where
}
// The only public interface to use the event loop
pub fn with_event_loop_context(event_loop: &ActiveEventLoop, f: impl FnOnce()) {
pub fn with_event_loop_context(event_loop: &dyn ActiveEventLoop, f: impl FnOnce()) {
// NOTE: For safety, this guard must NOT be leaked.
let _guard = EventLoopGuard::new(event_loop);
f();

View File

@@ -15,12 +15,12 @@ use crate::{
};
// ----------------------------------------------------------------------------
fn create_event_loop(native_options: &mut epi::NativeOptions) -> Result<EventLoop<UserEvent>> {
fn create_event_loop(native_options: &mut epi::NativeOptions) -> Result<EventLoop> {
#[cfg(target_os = "android")]
use winit::platform::android::EventLoopBuilderExtAndroid as _;
profiling::function_scope!();
let mut builder = winit::event_loop::EventLoop::with_user_event();
let mut builder = winit::event_loop::EventLoop::builder();
#[cfg(target_os = "android")]
let mut builder =
@@ -45,9 +45,9 @@ fn create_event_loop(native_options: &mut epi::NativeOptions) -> Result<EventLoo
#[cfg(not(target_os = "ios"))]
fn with_event_loop<R>(
mut native_options: epi::NativeOptions,
f: impl FnOnce(&mut EventLoop<UserEvent>, epi::NativeOptions) -> R,
f: impl FnOnce(&mut EventLoop, epi::NativeOptions) -> R,
) -> Result<R> {
thread_local!(static EVENT_LOOP: std::cell::RefCell<Option<EventLoop<UserEvent>>> = const { std::cell::RefCell::new(None) });
thread_local!(static EVENT_LOOP: std::cell::RefCell<Option<EventLoop>> = const { std::cell::RefCell::new(None) });
EVENT_LOOP.with(|event_loop| {
// Since we want to reference NativeOptions when creating the EventLoop we can't
@@ -84,7 +84,7 @@ impl<T: WinitApp> WinitAppWrapper<T> {
fn handle_event_result(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
event_result: Result<EventResult>,
) {
let mut exit = false;
@@ -174,7 +174,7 @@ impl<T: WinitApp> WinitAppWrapper<T> {
self.check_redraw_requests(event_loop);
}
fn check_redraw_requests(&mut self, event_loop: &ActiveEventLoop) {
fn check_redraw_requests(&mut self, event_loop: &dyn ActiveEventLoop) {
let now = Instant::now();
self.windows_next_repaint_times
@@ -201,8 +201,8 @@ impl<T: WinitApp> WinitAppWrapper<T> {
}
}
impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
impl<T: WinitApp> ApplicationHandler for WinitAppWrapper<T> {
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) {
profiling::scope!("Event::Suspended");
event_loop_context::with_event_loop_context(event_loop, move || {
@@ -211,7 +211,7 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
});
}
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) {
profiling::scope!("Event::Resumed");
// Nb: Make sure this guard is dropped after this function returns.
@@ -221,19 +221,19 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
});
}
fn exiting(&mut self, event_loop: &ActiveEventLoop) {
// On Mac, Cmd-Q we get here and then `run_app_on_demand` doesn't return (despite its name),
// so we need to save state now:
log::debug!("Received Event::LoopExiting - saving app state…");
event_loop_context::with_event_loop_context(event_loop, move || {
self.winit_app.save_and_destroy();
});
}
// fn exiting(&mut self, event_loop: &ActiveEventLoop) {
// // On Mac, Cmd-Q we get here and then `run_app_on_demand` doesn't return (despite its name),
// // so we need to save state now:
// log::debug!("Received Event::LoopExiting - saving app state…");
// event_loop_context::with_event_loop_context(event_loop, move || {
// self.winit_app.save_and_destroy();
// });
// }
fn device_event(
&mut self,
event_loop: &ActiveEventLoop,
device_id: winit::event::DeviceId,
event_loop: &dyn ActiveEventLoop,
device_id: Option<winit::event::DeviceId>,
event: winit::event::DeviceEvent,
) {
profiling::function_scope!(egui_winit::short_device_event_description(&event));
@@ -245,50 +245,51 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
});
}
fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
profiling::function_scope!(match &event {
UserEvent::RequestRepaint { .. } => "UserEvent::RequestRepaint",
#[cfg(feature = "accesskit")]
UserEvent::AccessKitActionRequest(_) => "UserEvent::AccessKitActionRequest",
});
// TODO: User event handling?
// fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
// profiling::function_scope!(match &event {
// UserEvent::RequestRepaint { .. } => "UserEvent::RequestRepaint",
// #[cfg(feature = "accesskit")]
// UserEvent::AccessKitActionRequest(_) => "UserEvent::AccessKitActionRequest",
// });
//
// event_loop_context::with_event_loop_context(event_loop, move || {
// let event_result = match event {
// UserEvent::RequestRepaint {
// when,
// cumulative_pass_nr,
// viewport_id,
// } => {
// let current_pass_nr = self
// .winit_app
// .egui_ctx()
// .map_or(0, |ctx| ctx.cumulative_pass_nr_for(viewport_id));
// if current_pass_nr == cumulative_pass_nr
// || current_pass_nr == cumulative_pass_nr + 1
// {
// log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}");
// if let Some(window_id) =
// self.winit_app.window_id_from_viewport_id(viewport_id)
// {
// Ok(EventResult::RepaintAt(window_id, when))
// } else {
// Ok(EventResult::Wait)
// }
// } else {
// log::trace!("Got outdated UserEvent::RequestRepaint");
// Ok(EventResult::Wait) // old request - we've already repainted
// }
// }
// #[cfg(feature = "accesskit")]
// UserEvent::AccessKitActionRequest(request) => {
// self.winit_app.on_accesskit_event(request)
// }
// };
// self.handle_event_result(event_loop, event_result);
// });
// }
event_loop_context::with_event_loop_context(event_loop, move || {
let event_result = match event {
UserEvent::RequestRepaint {
when,
cumulative_pass_nr,
viewport_id,
} => {
let current_pass_nr = self
.winit_app
.egui_ctx()
.map_or(0, |ctx| ctx.cumulative_pass_nr_for(viewport_id));
if current_pass_nr == cumulative_pass_nr
|| current_pass_nr == cumulative_pass_nr + 1
{
log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}");
if let Some(window_id) =
self.winit_app.window_id_from_viewport_id(viewport_id)
{
Ok(EventResult::RepaintAt(window_id, when))
} else {
Ok(EventResult::Wait)
}
} else {
log::trace!("Got outdated UserEvent::RequestRepaint");
Ok(EventResult::Wait) // old request - we've already repainted
}
}
#[cfg(feature = "accesskit")]
UserEvent::AccessKitActionRequest(request) => {
self.winit_app.on_accesskit_event(request)
}
};
self.handle_event_result(event_loop, event_result);
});
}
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: winit::event::StartCause) {
fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: winit::event::StartCause) {
if let winit::event::StartCause::ResumeTimeReached { .. } = cause {
log::trace!("Woke up to check next_repaint_time");
}
@@ -298,7 +299,7 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: winit::event::WindowEvent,
) {
@@ -316,11 +317,15 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
self.handle_event_result(event_loop, event_result);
});
}
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
}
}
#[cfg(not(target_os = "ios"))]
fn run_and_return(event_loop: &mut EventLoop<UserEvent>, winit_app: impl WinitApp) -> Result {
use winit::platform::run_on_demand::EventLoopExtRunOnDemand as _;
fn run_and_return(event_loop: &mut EventLoop, winit_app: impl WinitApp) -> Result {
use winit_core::event_loop::run_on_demand::EventLoopExtRunOnDemand as _;
log::trace!("Entering the winit event loop (run_app_on_demand)…");
@@ -330,12 +335,16 @@ fn run_and_return(event_loop: &mut EventLoop<UserEvent>, winit_app: impl WinitAp
app.return_result
}
fn run_and_exit(event_loop: EventLoop<UserEvent>, winit_app: impl WinitApp) -> Result {
fn run_and_exit(event_loop: EventLoop, winit_app: impl WinitApp) -> Result {
log::trace!("Entering the winit event loop (run_app)…");
// When to repaint what window
let mut app = WinitAppWrapper::new(winit_app, false);
event_loop.run_app(&mut app)?;
// let mut app = Box::leak(Box::new(app)); // TODO: avoid leak
let app_mut: &mut dyn ApplicationHandler = &mut app;
#[allow(unsafe_code)]
let app_mut: &'static mut dyn ApplicationHandler = unsafe { std::mem::transmute(app_mut) }; // TODO: avoid unsafe
event_loop.run_app(app_mut)?;
log::debug!("winit event loop unexpectedly returned");
Ok(())
@@ -371,8 +380,8 @@ pub fn create_glow<'a>(
app_name: &str,
native_options: epi::NativeOptions,
app_creator: epi::AppCreator<'a>,
event_loop: &EventLoop<UserEvent>,
) -> impl ApplicationHandler<UserEvent> + 'a {
event_loop: &EventLoop,
) -> impl ApplicationHandler + 'a {
use super::glow_integration::GlowWinitApp;
let glow_eframe = GlowWinitApp::new(event_loop, app_name, native_options, app_creator);
@@ -409,8 +418,8 @@ pub fn create_wgpu<'a>(
app_name: &str,
native_options: epi::NativeOptions,
app_creator: epi::AppCreator<'a>,
event_loop: &EventLoop<UserEvent>,
) -> impl ApplicationHandler<UserEvent> + 'a {
event_loop: &EventLoop,
) -> impl ApplicationHandler + 'a {
use super::wgpu_integration::WgpuWinitApp;
let wgpu_eframe = WgpuWinitApp::new(event_loop, app_name, native_options, app_creator);
@@ -424,61 +433,65 @@ pub fn create_wgpu<'a>(
/// This can be run directly on your own [`EventLoop`] by itself or with other
/// windows you manage outside of eframe.
pub struct EframeWinitApplication<'a> {
wrapper: Box<dyn ApplicationHandler<UserEvent> + 'a>,
wrapper: Box<dyn ApplicationHandler + 'a>,
control_flow: ControlFlow,
}
impl ApplicationHandler<UserEvent> for EframeWinitApplication<'_> {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
impl ApplicationHandler for EframeWinitApplication<'_> {
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) {
self.wrapper.resumed(event_loop);
}
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: winit::window::WindowId,
event: winit::event::WindowEvent,
) {
self.wrapper.window_event(event_loop, window_id, event);
}
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: winit::event::StartCause) {
fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: winit::event::StartCause) {
self.wrapper.new_events(event_loop, cause);
}
fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
self.wrapper.user_event(event_loop, event);
}
// fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
// self.wrapper.user_event(event_loop, event);
// }
fn device_event(
&mut self,
event_loop: &ActiveEventLoop,
device_id: winit::event::DeviceId,
event_loop: &dyn ActiveEventLoop,
device_id: Option<winit::event::DeviceId>,
event: winit::event::DeviceEvent,
) {
self.wrapper.device_event(event_loop, device_id, event);
}
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
self.wrapper.about_to_wait(event_loop);
self.control_flow = event_loop.control_flow();
}
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) {
self.wrapper.suspended(event_loop);
}
fn exiting(&mut self, event_loop: &ActiveEventLoop) {
self.wrapper.exiting(event_loop);
// fn exiting(&mut self, event_loop: &ActiveEventLoop) {
// self.wrapper.exiting(event_loop);
// }
fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) {
self.wrapper.memory_warning(event_loop);
}
fn memory_warning(&mut self, event_loop: &ActiveEventLoop) {
self.wrapper.memory_warning(event_loop);
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
todo!()
}
}
impl<'a> EframeWinitApplication<'a> {
pub(crate) fn new<T: ApplicationHandler<UserEvent> + 'a>(app: T) -> Self {
pub(crate) fn new<T: ApplicationHandler + 'a>(app: T) -> Self {
Self {
wrapper: Box::new(app),
control_flow: ControlFlow::default(),
@@ -495,12 +508,12 @@ impl<'a> EframeWinitApplication<'a> {
#[cfg(not(target_os = "ios"))]
pub fn pump_eframe_app(
&mut self,
event_loop: &mut EventLoop<UserEvent>,
event_loop: &mut EventLoop,
timeout: Option<std::time::Duration>,
) -> EframePumpStatus {
use winit::platform::pump_events::{EventLoopExtPumpEvents as _, PumpStatus};
use winit_core::event_loop::pump_events::{EventLoopExtPumpEvents as _, PumpStatus};
match event_loop.pump_app_events(timeout, self) {
match event_loop.pump_app_events(timeout, &mut *self) {
PumpStatus::Continue => EframePumpStatus::Continue(self.control_flow),
PumpStatus::Exit(code) => EframePumpStatus::Exit(code),
}

View File

@@ -6,7 +6,7 @@
//! like removing a bunch of `unwraps`.
use std::{cell::RefCell, num::NonZeroU32, rc::Rc, sync::Arc, time::Instant};
use std::ops::Deref;
use egui_winit::ActionRequested;
use parking_lot::Mutex;
use raw_window_handle::{HasDisplayHandle as _, HasWindowHandle as _};
@@ -36,7 +36,7 @@ use super::{epi_integration, event_loop_context, winit_integration, winit_integr
// Types:
pub struct WgpuWinitApp<'app> {
repaint_proxy: Arc<Mutex<EventLoopProxy<UserEvent>>>,
repaint_proxy: Arc<Mutex<EventLoopProxy>>,
app_name: String,
native_options: NativeOptions,
@@ -89,7 +89,7 @@ pub struct Viewport {
/// Window surface state that's initialized when the app starts running via a Resumed event
/// and on Android will also be destroyed if the application is paused.
window: Option<Arc<Window>>,
window: Option<Arc<dyn Window>>,
/// `window` and `egui_winit` are initialized together.
egui_winit: Option<egui_winit::State>,
@@ -99,7 +99,7 @@ pub struct Viewport {
impl<'app> WgpuWinitApp<'app> {
pub fn new(
event_loop: &EventLoop<UserEvent>,
event_loop: &EventLoop,
app_name: &str,
native_options: NativeOptions,
app_creator: AppCreator<'app>,
@@ -122,7 +122,7 @@ impl<'app> WgpuWinitApp<'app> {
}
/// Create a window for all viewports lacking one.
fn initialized_all_windows(&mut self, event_loop: &ActiveEventLoop) {
fn initialized_all_windows(&mut self, event_loop: &dyn ActiveEventLoop) {
let Some(running) = &mut self.running else {
return;
};
@@ -178,9 +178,9 @@ impl<'app> WgpuWinitApp<'app> {
fn init_run_state(
&mut self,
egui_ctx: egui::Context,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
storage: Option<Box<dyn Storage>>,
window: Window,
window: Box<dyn Window>,
builder: ViewportBuilder,
) -> crate::Result<&mut WgpuWinitRunning<'app>> {
profiling::function_scope!();
@@ -200,12 +200,12 @@ impl<'app> WgpuWinitApp<'app> {
));
let mut viewport_info = ViewportInfo::default();
egui_winit::update_viewport_info(&mut viewport_info, &egui_ctx, &window, true);
egui_winit::update_viewport_info(&mut viewport_info, &egui_ctx, window.deref(), true);
{
// Tell egui right away about native_pixels_per_point etc,
// so that the app knows about it during app creation:
let pixels_per_point = egui_winit::pixels_per_point(&egui_ctx, &window);
let pixels_per_point = egui_winit::pixels_per_point(&egui_ctx, window.deref());
egui_ctx.input_mut(|i| {
i.raw
@@ -215,7 +215,7 @@ impl<'app> WgpuWinitApp<'app> {
});
}
let window = Arc::new(window);
let window: Arc<dyn Window> = Arc::from(window);
{
profiling::scope!("set_window");
@@ -226,7 +226,7 @@ impl<'app> WgpuWinitApp<'app> {
let integration = EpiIntegration::new(
egui_ctx.clone(),
&window,
window.deref(),
&self.app_name,
&self.native_options,
storage,
@@ -247,12 +247,14 @@ impl<'app> WgpuWinitApp<'app> {
event_loop_proxy
.lock()
.send_event(UserEvent::RequestRepaint {
when,
cumulative_pass_nr,
viewport_id: info.viewport_id,
})
.ok();
.wake_up();
// TODO: Pass user info somehow
// .send_event(UserEvent::RequestRepaint {
// when,
// cumulative_pass_nr,
// viewport_id: info.viewport_id,
// })
// .ok();
});
}
@@ -260,7 +262,7 @@ impl<'app> WgpuWinitApp<'app> {
let mut egui_winit = egui_winit::State::new(
egui_ctx.clone(),
ViewportId::ROOT,
event_loop,
&event_loop,
Some(window.scale_factor() as f32),
event_loop.system_theme(),
painter.max_texture_side(),
@@ -346,7 +348,7 @@ impl WinitApp for WgpuWinitApp<'_> {
self.running.as_ref().map(|r| &r.integration.egui_ctx)
}
fn window(&self, window_id: WindowId) -> Option<Arc<Window>> {
fn window(&self, window_id: WindowId) -> Option<Arc<dyn Window>> {
self.running
.as_ref()
.and_then(|r| {
@@ -386,7 +388,7 @@ impl WinitApp for WgpuWinitApp<'_> {
fn run_ui_and_paint(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
) -> Result<EventResult> {
self.initialized_all_windows(event_loop);
@@ -398,7 +400,7 @@ impl WinitApp for WgpuWinitApp<'_> {
}
}
fn resumed(&mut self, event_loop: &ActiveEventLoop) -> crate::Result<EventResult> {
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) -> crate::Result<EventResult> {
log::debug!("Event::Resumed");
let running = if let Some(running) = &self.running {
@@ -435,7 +437,7 @@ impl WinitApp for WgpuWinitApp<'_> {
}
}
fn suspended(&mut self, _: &ActiveEventLoop) -> crate::Result<EventResult> {
fn suspended(&mut self, _: &dyn ActiveEventLoop) -> crate::Result<EventResult> {
#[cfg(target_os = "android")]
self.drop_window()?;
Ok(EventResult::Save)
@@ -443,34 +445,35 @@ impl WinitApp for WgpuWinitApp<'_> {
fn device_event(
&mut self,
_: &ActiveEventLoop,
_: winit::event::DeviceId,
_: &dyn ActiveEventLoop,
_: Option<winit::event::DeviceId>,
event: winit::event::DeviceEvent,
) -> crate::Result<EventResult> {
if let winit::event::DeviceEvent::MouseMotion { delta } = event
&& let Some(running) = &mut self.running
{
let mut shared = running.shared.borrow_mut();
if let Some(viewport) = shared
.focused_viewport
.and_then(|viewport| shared.viewports.get_mut(&viewport))
{
if let Some(egui_winit) = viewport.egui_winit.as_mut() {
egui_winit.on_mouse_motion(delta);
}
if let Some(window) = viewport.window.as_ref() {
return Ok(EventResult::RepaintNext(window.id()));
}
}
}
// TODO
// if let winit::event::DeviceEvent::MouseMotion { delta } = event
// && let Some(running) = &mut self.running
// {
// let mut shared = running.shared.borrow_mut();
// if let Some(viewport) = shared
// .focused_viewport
// .and_then(|viewport| shared.viewports.get_mut(&viewport))
// {
// if let Some(egui_winit) = viewport.egui_winit.as_mut() {
// egui_winit.on_mouse_motion(delta);
// }
//
// if let Some(window) = viewport.window.as_ref() {
// return Ok(EventResult::RepaintNext(window.id()));
// }
// }
// }
Ok(EventResult::Wait)
}
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: winit::event::WindowEvent,
) -> crate::Result<EventResult> {
@@ -606,7 +609,7 @@ impl WgpuWinitRunning<'_> {
let Some(window) = window else {
return Ok(EventResult::Wait);
};
egui_winit::update_viewport_info(info, &integration.egui_ctx, window, false);
egui_winit::update_viewport_info(info, &integration.egui_ctx, window.deref().deref(), false);
{
profiling::scope!("set_window");
@@ -616,7 +619,7 @@ impl WgpuWinitRunning<'_> {
let Some(egui_winit) = egui_winit.as_mut() else {
return Ok(EventResult::Wait);
};
let mut raw_input = egui_winit.take_egui_input(window);
let mut raw_input = egui_winit.take_egui_input(window.deref().deref());
integration.pre_update();
@@ -674,7 +677,7 @@ impl WgpuWinitRunning<'_> {
return Ok(EventResult::Wait);
};
egui_winit.handle_platform_output(window, platform_output);
egui_winit.handle_platform_output(&**window, platform_output);
let clipped_primitives = egui_ctx.tessellate(shapes, pixels_per_point);
@@ -721,7 +724,7 @@ impl WgpuWinitRunning<'_> {
}
}
integration.post_rendering(window);
integration.post_rendering(&**window);
let active_viewports_ids: ViewportIdSet = viewport_output.keys().copied().collect();
@@ -824,24 +827,25 @@ impl WgpuWinitRunning<'_> {
shared.focused_viewport = focused.then_some(viewport_id).flatten();
}
winit::event::WindowEvent::Resized(physical_size) => {
// Resize with 0 width and height is used by winit to signal a minimize event on Windows.
// See: https://github.com/rust-windowing/winit/issues/208
// This solves an issue where the app would panic when minimizing on Windows.
if let Some(id) = viewport_id
&& let (Some(width), Some(height)) = (
NonZeroU32::new(physical_size.width),
NonZeroU32::new(physical_size.height),
)
{
if shared.resized_viewport != viewport_id {
shared.resized_viewport = viewport_id;
shared.painter.on_window_resize_state_change(id, true);
}
shared.painter.on_window_resized(id, width, height);
repaint_asap = true;
}
}
// TODO
// winit::event::WindowEvent::Resized(physical_size) => {
// // Resize with 0 width and height is used by winit to signal a minimize event on Windows.
// // See: https://github.com/rust-windowing/winit/issues/208
// // This solves an issue where the app would panic when minimizing on Windows.
// if let Some(id) = viewport_id
// && let (Some(width), Some(height)) = (
// NonZeroU32::new(physical_size.width),
// NonZeroU32::new(physical_size.height),
// )
// {
// if shared.resized_viewport != viewport_id {
// shared.resized_viewport = viewport_id;
// shared.painter.on_window_resize_state_change(id, true);
// }
// shared.painter.on_window_resized(id, width, height);
// repaint_asap = true;
// }
// }
winit::event::WindowEvent::CloseRequested => {
if viewport_id == Some(ViewportId::ROOT) && integration.should_close() {
@@ -899,7 +903,7 @@ impl Viewport {
/// Create winit window, if needed.
fn initialize_window(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
egui_ctx: &egui::Context,
windows_id: &mut HashMap<WindowId, ViewportId>,
painter: &mut egui_wgpu::winit::Painter,
@@ -916,7 +920,7 @@ impl Viewport {
Ok(window) => {
windows_id.insert(window.id(), viewport_id);
let window = Arc::new(window);
let window: Arc<dyn Window> = Arc::from(window);
if let Err(err) =
pollster::block_on(painter.set_window(viewport_id, Some(window.clone())))
@@ -927,13 +931,13 @@ impl Viewport {
self.egui_winit = Some(egui_winit::State::new(
egui_ctx.clone(),
viewport_id,
event_loop,
&event_loop,
Some(window.scale_factor() as f32),
event_loop.system_theme(),
painter.max_texture_side(),
));
egui_winit::update_viewport_info(&mut self.info, egui_ctx, &window, true);
egui_winit::update_viewport_info(&mut self.info, egui_ctx, &*window, true);
self.window = Some(window);
}
Err(err) => {
@@ -945,10 +949,10 @@ impl Viewport {
fn create_window(
egui_ctx: &egui::Context,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
storage: Option<&dyn Storage>,
native_options: &mut NativeOptions,
) -> Result<(Window, ViewportBuilder), winit::error::OsError> {
) -> Result<(Box<dyn Window>, ViewportBuilder), winit::error::RequestError> {
profiling::function_scope!();
let window_settings = epi_integration::load_window_settings(storage);
@@ -961,7 +965,7 @@ fn create_window(
.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 = egui_winit::create_window(egui_ctx, event_loop, &viewport_builder)?;
epi_integration::apply_window_settings(&window, window_settings);
epi_integration::apply_window_settings(&*window, window_settings);
Ok((window, viewport_builder))
}
@@ -1004,9 +1008,9 @@ fn render_immediate_viewport(
let (Some(window), Some(egui_winit)) = (&viewport.window, &mut viewport.egui_winit) else {
return;
};
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, window, false);
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, &**window, false);
let mut input = egui_winit.take_egui_input(window);
let mut input = egui_winit.take_egui_input(&**window);
input.viewports = viewports
.iter()
.map(|(id, viewport)| (*id, viewport.info.clone()))
@@ -1069,7 +1073,7 @@ fn render_immediate_viewport(
vec![],
);
egui_winit.handle_platform_output(window, platform_output);
egui_winit.handle_platform_output(&**window, platform_output);
handle_viewport_output(
&egui_ctx,
@@ -1120,7 +1124,7 @@ fn handle_viewport_output(
initialize_or_update_viewport(viewports, ids, class, builder, viewport_ui_cb, painter);
if let Some(window) = viewport.window.as_ref() {
let old_inner_size = window.inner_size();
let old_inner_size = window.surface_size();
viewport.deferred_commands.append(&mut commands);
@@ -1128,13 +1132,13 @@ fn handle_viewport_output(
egui_ctx,
&mut viewport.info,
std::mem::take(&mut viewport.deferred_commands),
window,
&**window,
&mut viewport.actions_requested,
);
// For Wayland : https://github.com/emilk/egui/issues/4196
if cfg!(target_os = "linux") {
let new_inner_size = window.inner_size();
let new_inner_size = window.surface_size();
if new_inner_size != old_inner_size
&& let (Some(width), Some(height)) = (
NonZeroU32::new(new_inner_size.width),

View File

@@ -66,7 +66,7 @@ impl From<accesskit_winit::Event> for UserEvent {
pub trait WinitApp {
fn egui_ctx(&self) -> Option<&egui::Context>;
fn window(&self, window_id: WindowId) -> Option<Arc<Window>>;
fn window(&self, window_id: WindowId) -> Option<Arc<dyn Window>>;
fn window_id_from_viewport_id(&self, id: ViewportId) -> Option<WindowId>;
@@ -76,24 +76,24 @@ pub trait WinitApp {
fn run_ui_and_paint(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
) -> crate::Result<EventResult>;
fn suspended(&mut self, event_loop: &ActiveEventLoop) -> crate::Result<EventResult>;
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) -> crate::Result<EventResult>;
fn resumed(&mut self, event_loop: &ActiveEventLoop) -> crate::Result<EventResult>;
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) -> crate::Result<EventResult>;
fn device_event(
&mut self,
event_loop: &ActiveEventLoop,
device_id: winit::event::DeviceId,
event_loop: &dyn ActiveEventLoop,
device_id: Option<winit::event::DeviceId>,
event: winit::event::DeviceEvent,
) -> crate::Result<EventResult>;
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: winit::event::WindowEvent,
) -> crate::Result<EventResult>;

View File

@@ -31,7 +31,7 @@ default = ["fragile-send-sync-non-atomic-wasm", "macos-window-resize-jitter-fix"
capture = ["dep:egui"]
## Enable [`winit`](https://docs.rs/winit) integration. On Linux, requires either `wayland` or `x11`
winit = ["dep:winit", "winit/rwh_06", "dep:egui", "capture"]
winit = ["dep:winit", "dep:egui", "capture"]
## Enables Wayland support for winit.
wayland = ["winit?/wayland"]

View File

@@ -143,12 +143,12 @@ impl Painter {
pub async fn set_window(
&mut self,
viewport_id: ViewportId,
window: Option<Arc<winit::window::Window>>,
window: Option<Arc<dyn winit::window::Window>>,
) -> Result<(), crate::WgpuError> {
profiling::scope!("Painter::set_window"); // profile_function gives bad names for async functions
if let Some(window) = window {
let size = window.inner_size();
let size = window.surface_size();
if !self.surfaces.contains_key(&viewport_id) {
let surface = self.instance.create_surface(window)?;
self.add_surface(surface, viewport_id, size).await?;
@@ -169,12 +169,12 @@ impl Painter {
pub async unsafe fn set_window_unsafe(
&mut self,
viewport_id: ViewportId,
window: Option<&winit::window::Window>,
window: Option<&dyn winit::window::Window>,
) -> Result<(), crate::WgpuError> {
profiling::scope!("Painter::set_window_unsafe"); // profile_function gives bad names for async functions
if let Some(window) = window {
let size = window.inner_size();
let size = window.surface_size();
if !self.surfaces.contains_key(&viewport_id) {
let surface = unsafe {
self.instance

View File

@@ -57,11 +57,13 @@ x11 = ["winit/x11", "bytemuck"]
[dependencies]
egui = { workspace = true, default-features = false }
dpi.workspace = true
log.workspace = true
profiling.workspace = true
raw-window-handle.workspace = true
web-time.workspace = true
winit = { workspace = true, default-features = false }
winit-core.workspace = true
#! ### Optional dependencies

View File

@@ -9,6 +9,7 @@
#![allow(clippy::manual_range_contains)]
use std::ops::Deref;
#[cfg(feature = "accesskit")]
pub use accesskit_winit;
pub use egui;
@@ -31,21 +32,22 @@ use winit::{
event_loop::ActiveEventLoop,
window::{CursorGrabMode, Window, WindowButtons, WindowLevel},
};
use winit_core::event::Ime;
pub fn screen_size_in_pixels(window: &Window) -> egui::Vec2 {
pub fn screen_size_in_pixels(window: &dyn Window) -> egui::Vec2 {
let size = if cfg!(target_os = "ios") {
// `outer_size` Includes the area behind the "dynamic island".
// It is up to the eframe user to make sure the dynamic island doesn't cover anything important.
// That will be easier once https://github.com/rust-windowing/winit/pull/3890 lands
window.outer_size()
} else {
window.inner_size()
window.surface_size()
};
egui::vec2(size.width as f32, size.height as f32)
}
/// Calculate the `pixels_per_point` for a given window, given the current egui zoom factor
pub fn pixels_per_point(egui_ctx: &egui::Context, window: &Window) -> f32 {
pub fn pixels_per_point(egui_ctx: &egui::Context, window: &dyn Window) -> f32 {
let native_pixels_per_point = window.scale_factor() as f32;
let egui_zoom_factor = egui_ctx.zoom_factor();
egui_zoom_factor * native_pixels_per_point
@@ -166,9 +168,9 @@ impl State {
#[cfg(feature = "accesskit")]
pub fn init_accesskit<T: From<accesskit_winit::Event> + Send>(
&mut self,
event_loop: &ActiveEventLoop,
window: &Window,
event_loop_proxy: winit::event_loop::EventLoopProxy<T>,
event_loop: &dyn ActiveEventLoop,
window: &dyn Window,
event_loop_proxy: winit::event_loop::EventLoopProxy,
) {
profiling::function_scope!();
@@ -231,7 +233,7 @@ impl State {
/// You need to set [`egui::RawInput::viewports`] yourself though.
/// Use [`update_viewport_info`] to update the info for each
/// viewport.
pub fn take_egui_input(&mut self, window: &Window) -> egui::RawInput {
pub fn take_egui_input(&mut self, window: &dyn Window) -> egui::RawInput {
profiling::function_scope!();
self.egui_input.time = Some(self.start_time.elapsed().as_secs_f64());
@@ -264,7 +266,7 @@ impl State {
/// The result can be found in [`Self::egui_input`] and be extracted with [`Self::take_egui_input`].
pub fn on_window_event(
&mut self,
window: &Window,
window: &dyn Window,
event: &winit::event::WindowEvent,
) -> EventResponse {
profiling::function_scope!(short_window_event_description(event));
@@ -305,13 +307,13 @@ impl State {
consumed: false,
}
}
WindowEvent::MouseInput { state, button, .. } => {
self.on_mouse_button_input(*state, *button);
EventResponse {
repaint: true,
consumed: self.egui_ctx.wants_pointer_input(),
}
}
// WindowEvent::MouseInput { state, button, .. } => {
// self.on_mouse_button_input(*state, *button);
// EventResponse {
// repaint: true,
// consumed: self.egui_ctx.wants_pointer_input(),
// }
// }
WindowEvent::MouseWheel { delta, phase, .. } => {
self.on_mouse_wheel(window, *delta, *phase);
EventResponse {
@@ -319,35 +321,35 @@ impl State {
consumed: self.egui_ctx.wants_pointer_input(),
}
}
WindowEvent::CursorMoved { position, .. } => {
self.on_cursor_moved(window, *position);
EventResponse {
repaint: true,
consumed: self.egui_ctx.is_using_pointer(),
}
}
WindowEvent::CursorLeft { .. } => {
self.pointer_pos_in_points = None;
self.egui_input.events.push(egui::Event::PointerGone);
EventResponse {
repaint: true,
consumed: false,
}
}
// WindowEvent::TouchpadPressure {device_id, pressure, stage, .. } => {} // TODO(emilk)
WindowEvent::Touch(touch) => {
self.on_touch(window, touch);
let consumed = match touch.phase {
winit::event::TouchPhase::Started
| winit::event::TouchPhase::Ended
| winit::event::TouchPhase::Cancelled => self.egui_ctx.wants_pointer_input(),
winit::event::TouchPhase::Moved => self.egui_ctx.is_using_pointer(),
};
EventResponse {
repaint: true,
consumed,
}
}
// WindowEvent::CursorMoved { position, .. } => {
// self.on_cursor_moved(window, *position);
// EventResponse {
// repaint: true,
// consumed: self.egui_ctx.is_using_pointer(),
// }
// }
// WindowEvent::CursorLeft { .. } => {
// self.pointer_pos_in_points = None;
// self.egui_input.events.push(egui::Event::PointerGone);
// EventResponse {
// repaint: true,
// consumed: false,
// }
// }
// // WindowEvent::TouchpadPressure {device_id, pressure, stage, .. } => {} // TODO(emilk)
// WindowEvent::PointerButton(touch) => {
// self.on_touch(window, touch);
// let consumed = match touch.phase {
// winit::event::TouchPhase::Started
// | winit::event::TouchPhase::Ended
// | winit::event::TouchPhase::Cancelled => self.egui_ctx.wants_pointer_input(),
// winit::event::TouchPhase::Moved => self.egui_ctx.is_using_pointer(),
// };
// EventResponse {
// repaint: true,
// consumed,
// }
// }
WindowEvent::Ime(ime) => {
// on Mac even Cmd-C is pressed during ime, a `c` is pushed to Preedit.
@@ -388,6 +390,9 @@ impl State {
winit::event::Ime::Disabled | winit::event::Ime::Preedit(_, None) => {
self.ime_event_disable();
}
Ime::DeleteSurrounding { .. } => {
todo!()
}
}
EventResponse {
@@ -448,41 +453,41 @@ impl State {
consumed: false,
}
}
WindowEvent::HoveredFile(path) => {
self.egui_input.hovered_files.push(egui::HoveredFile {
path: Some(path.clone()),
..Default::default()
});
EventResponse {
repaint: true,
consumed: false,
}
}
WindowEvent::HoveredFileCancelled => {
self.egui_input.hovered_files.clear();
EventResponse {
repaint: true,
consumed: false,
}
}
WindowEvent::DroppedFile(path) => {
self.egui_input.hovered_files.clear();
self.egui_input.dropped_files.push(egui::DroppedFile {
path: Some(path.clone()),
..Default::default()
});
EventResponse {
repaint: true,
consumed: false,
}
}
// WindowEvent::HoveredFile(path) => {
// self.egui_input.hovered_files.push(egui::HoveredFile {
// path: Some(path.clone()),
// ..Default::default()
// });
// EventResponse {
// repaint: true,
// consumed: false,
// }
// }
// WindowEvent::HoveredFileCancelled => {
// self.egui_input.hovered_files.clear();
// EventResponse {
// repaint: true,
// consumed: false,
// }
// }
// WindowEvent::DroppedFile(path) => {
// self.egui_input.hovered_files.clear();
// self.egui_input.dropped_files.push(egui::DroppedFile {
// path: Some(path.clone()),
// ..Default::default()
// });
// EventResponse {
// repaint: true,
// consumed: false,
// }
// }
WindowEvent::ModifiersChanged(state) => {
let state = state.state();
let alt = state.alt_key();
let ctrl = state.control_key();
let shift = state.shift_key();
let super_ = state.super_key();
let super_ = state.meta_key();
self.egui_input.modifiers.alt = alt;
self.egui_input.modifiers.ctrl = ctrl;
@@ -502,10 +507,10 @@ impl State {
// Things that may require repaint:
WindowEvent::RedrawRequested
| WindowEvent::CursorEntered { .. }
// | WindowEvent::CursorEntered { .. }
| WindowEvent::Destroyed
| WindowEvent::Occluded(_)
| WindowEvent::Resized(_)
// | WindowEvent::Resized(_)
| WindowEvent::Moved(_)
| WindowEvent::TouchpadPressure { .. }
| WindowEvent::CloseRequested => EventResponse {
@@ -515,7 +520,7 @@ impl State {
// Things we completely ignore:
WindowEvent::ActivationTokenDone { .. }
| WindowEvent::AxisMotion { .. }
// | WindowEvent::AxisMotion { .. }
| WindowEvent::DoubleTapGesture { .. } => EventResponse {
repaint: false,
consumed: false,
@@ -559,6 +564,20 @@ impl State {
consumed: self.egui_ctx.wants_pointer_input(),
}
}
// WindowEvent::SurfaceResized(_) => {}
// WindowEvent::DragEntered { .. } => {}
// WindowEvent::DragMoved { .. } => {}
// WindowEvent::DragDropped { .. } => {}
// WindowEvent::DragLeft { .. } => {}
// WindowEvent::PointerMoved { .. } => {}
// WindowEvent::PointerEntered { .. } => {}
// WindowEvent::PointerLeft { .. } => {}
// WindowEvent::PointerButton { .. } => {}
// TODO: Handle these
_ => EventResponse {
repaint: false,
consumed: false,
},
}
}
@@ -642,7 +661,7 @@ impl State {
fn on_cursor_moved(
&mut self,
window: &Window,
window: &dyn Window,
pos_in_pixels: winit::dpi::PhysicalPosition<f64>,
) {
let pixels_per_point = pixels_per_point(&self.egui_ctx, window);
@@ -674,69 +693,69 @@ impl State {
}
}
fn on_touch(&mut self, window: &Window, touch: &winit::event::Touch) {
let pixels_per_point = pixels_per_point(&self.egui_ctx, window);
// Emit touch event
self.egui_input.events.push(egui::Event::Touch {
device_id: egui::TouchDeviceId(egui::epaint::util::hash(touch.device_id)),
id: egui::TouchId::from(touch.id),
phase: to_egui_touch_phase(touch.phase),
pos: egui::pos2(
touch.location.x as f32 / pixels_per_point,
touch.location.y as f32 / pixels_per_point,
),
force: match touch.force {
Some(winit::event::Force::Normalized(force)) => Some(force as f32),
Some(winit::event::Force::Calibrated {
force,
max_possible_force,
..
}) => Some((force / max_possible_force) as f32),
None => None,
},
});
// If we're not yet translating a touch or we're translating this very
// touch …
if self.pointer_touch_id.is_none() || self.pointer_touch_id.unwrap_or_default() == touch.id
{
// … emit PointerButton resp. PointerMoved events to emulate mouse
match touch.phase {
winit::event::TouchPhase::Started => {
self.pointer_touch_id = Some(touch.id);
// First move the pointer to the right location
self.on_cursor_moved(window, touch.location);
self.on_mouse_button_input(
winit::event::ElementState::Pressed,
winit::event::MouseButton::Left,
);
}
winit::event::TouchPhase::Moved => {
self.on_cursor_moved(window, touch.location);
}
winit::event::TouchPhase::Ended => {
self.pointer_touch_id = None;
self.on_mouse_button_input(
winit::event::ElementState::Released,
winit::event::MouseButton::Left,
);
// The pointer should vanish completely to not get any
// hover effects
self.pointer_pos_in_points = None;
self.egui_input.events.push(egui::Event::PointerGone);
}
winit::event::TouchPhase::Cancelled => {
self.pointer_touch_id = None;
self.pointer_pos_in_points = None;
self.egui_input.events.push(egui::Event::PointerGone);
}
}
}
}
// fn on_touch(&mut self, window: &Window, touch: &winit::event::Touch) {
// let pixels_per_point = pixels_per_point(&self.egui_ctx, window);
//
// // Emit touch event
// self.egui_input.events.push(egui::Event::Touch {
// device_id: egui::TouchDeviceId(egui::epaint::util::hash(touch.device_id)),
// id: egui::TouchId::from(touch.id),
// phase: to_egui_touch_phase(touch.phase),
// pos: egui::pos2(
// touch.location.x as f32 / pixels_per_point,
// touch.location.y as f32 / pixels_per_point,
// ),
// force: match touch.force {
// Some(winit::event::Force::Normalized(force)) => Some(force as f32),
// Some(winit::event::Force::Calibrated {
// force,
// max_possible_force,
// ..
// }) => Some((force / max_possible_force) as f32),
// None => None,
// },
// });
// // If we're not yet translating a touch or we're translating this very
// // touch …
// if self.pointer_touch_id.is_none() || self.pointer_touch_id.unwrap_or_default() == touch.id
// {
// // … emit PointerButton resp. PointerMoved events to emulate mouse
// match touch.phase {
// winit::event::TouchPhase::Started => {
// self.pointer_touch_id = Some(touch.id);
// // First move the pointer to the right location
// self.on_cursor_moved(window, touch.location);
// self.on_mouse_button_input(
// winit::event::ElementState::Pressed,
// winit::event::MouseButton::Left,
// );
// }
// winit::event::TouchPhase::Moved => {
// self.on_cursor_moved(window, touch.location);
// }
// winit::event::TouchPhase::Ended => {
// self.pointer_touch_id = None;
// self.on_mouse_button_input(
// winit::event::ElementState::Released,
// winit::event::MouseButton::Left,
// );
// // The pointer should vanish completely to not get any
// // hover effects
// self.pointer_pos_in_points = None;
// self.egui_input.events.push(egui::Event::PointerGone);
// }
// winit::event::TouchPhase::Cancelled => {
// self.pointer_touch_id = None;
// self.pointer_pos_in_points = None;
// self.egui_input.events.push(egui::Event::PointerGone);
// }
// }
// }
// }
fn on_mouse_wheel(
&mut self,
window: &Window,
window: &dyn Window,
delta: winit::event::MouseScrollDelta,
phase: winit::event::TouchPhase,
) {
@@ -877,7 +896,7 @@ impl State {
/// *
pub fn handle_platform_output(
&mut self,
window: &Window,
window: &dyn Window,
platform_output: egui::PlatformOutput,
) {
profiling::function_scope!();
@@ -929,11 +948,13 @@ impl State {
winit::dpi::PhysicalPosition {
x: ime_rect_px.min.x,
y: ime_rect_px.min.y,
},
}
.into(),
winit::dpi::PhysicalSize {
width: ime_rect_px.width(),
height: ime_rect_px.height(),
},
}
.into(),
);
}
} else {
@@ -949,7 +970,7 @@ impl State {
}
}
fn set_cursor_icon(&mut self, window: &Window, cursor_icon: egui::CursorIcon) {
fn set_cursor_icon(&mut self, window: &dyn Window, cursor_icon: egui::CursorIcon) {
if self.current_cursor_icon == Some(cursor_icon) {
// Prevent flickering near frame boundary when Windows OS tries to control cursor icon for window resizing.
// On other platforms: just early-out to save CPU.
@@ -960,12 +981,7 @@ impl State {
if is_pointer_in_window {
self.current_cursor_icon = Some(cursor_icon);
if let Some(winit_cursor_icon) = translate_cursor(cursor_icon) {
window.set_cursor_visible(true);
window.set_cursor(winit_cursor_icon);
} else {
window.set_cursor_visible(false);
}
window.set_cursor_visible(true);
} else {
// Remember to set the cursor again once the cursor returns to the screen:
self.current_cursor_icon = None;
@@ -989,11 +1005,11 @@ fn to_egui_theme(theme: winit::window::Theme) -> Theme {
}
}
pub fn inner_rect_in_points(window: &Window, pixels_per_point: f32) -> Option<Rect> {
let inner_pos_px = window.inner_position().ok()?;
pub fn inner_rect_in_points(window: &dyn Window, pixels_per_point: f32) -> Option<Rect> {
let inner_pos_px = window.surface_position();
let inner_pos_px = egui::pos2(inner_pos_px.x as f32, inner_pos_px.y as f32);
let inner_size_px = window.inner_size();
let inner_size_px = window.surface_size();
let inner_size_px = egui::vec2(inner_size_px.width as f32, inner_size_px.height as f32);
let inner_rect_px = egui::Rect::from_min_size(inner_pos_px, inner_size_px);
@@ -1001,7 +1017,7 @@ pub fn inner_rect_in_points(window: &Window, pixels_per_point: f32) -> Option<Re
Some(inner_rect_px / pixels_per_point)
}
pub fn outer_rect_in_points(window: &Window, pixels_per_point: f32) -> Option<Rect> {
pub fn outer_rect_in_points(window: &dyn Window, pixels_per_point: f32) -> Option<Rect> {
let outer_pos_px = window.outer_position().ok()?;
let outer_pos_px = egui::pos2(outer_pos_px.x as f32, outer_pos_px.y as f32);
@@ -1021,7 +1037,7 @@ pub fn outer_rect_in_points(window: &Window, pixels_per_point: f32) -> Option<Re
pub fn update_viewport_info(
viewport_info: &mut ViewportInfo,
egui_ctx: &egui::Context,
window: &Window,
window: &dyn Window,
is_init: bool,
) {
profiling::function_scope!();
@@ -1047,8 +1063,9 @@ pub fn update_viewport_info(
let monitor_size = {
profiling::scope!("monitor_size");
if let Some(monitor) = window.current_monitor() {
let size = monitor.size().to_logical::<f32>(pixels_per_point.into());
Some(egui::vec2(size.width, size.height))
// let size = monitor.size().to_logical::<f32>(pixels_per_point.into());
// Some(egui::vec2(size.width, size.height))
None // TODO
} else {
None
}
@@ -1122,7 +1139,8 @@ fn translate_mouse_button(button: winit::event::MouseButton) -> Option<egui::Poi
winit::event::MouseButton::Middle => Some(egui::PointerButton::Middle),
winit::event::MouseButton::Back => Some(egui::PointerButton::Extra1),
winit::event::MouseButton::Forward => Some(egui::PointerButton::Extra2),
winit::event::MouseButton::Other(_) => None,
_ => None
// winit::event::MouseButton::Other(_) => None,
}
}
@@ -1157,7 +1175,7 @@ fn key_from_named_key(named_key: winit::keyboard::NamedKey) -> Option<egui::Key>
NamedKey::Copy => Key::Copy,
NamedKey::Paste => Key::Paste,
NamedKey::Space => Key::Space,
// NamedKey::SpaSpace => Key::Space, TODO: ??
NamedKey::F1 => Key::F1,
NamedKey::F2 => Key::F2,
@@ -1325,50 +1343,6 @@ fn key_from_key_code(key: winit::keyboard::KeyCode) -> Option<egui::Key> {
})
}
fn translate_cursor(cursor_icon: egui::CursorIcon) -> Option<winit::window::CursorIcon> {
match cursor_icon {
egui::CursorIcon::None => None,
egui::CursorIcon::Alias => Some(winit::window::CursorIcon::Alias),
egui::CursorIcon::AllScroll => Some(winit::window::CursorIcon::AllScroll),
egui::CursorIcon::Cell => Some(winit::window::CursorIcon::Cell),
egui::CursorIcon::ContextMenu => Some(winit::window::CursorIcon::ContextMenu),
egui::CursorIcon::Copy => Some(winit::window::CursorIcon::Copy),
egui::CursorIcon::Crosshair => Some(winit::window::CursorIcon::Crosshair),
egui::CursorIcon::Default => Some(winit::window::CursorIcon::Default),
egui::CursorIcon::Grab => Some(winit::window::CursorIcon::Grab),
egui::CursorIcon::Grabbing => Some(winit::window::CursorIcon::Grabbing),
egui::CursorIcon::Help => Some(winit::window::CursorIcon::Help),
egui::CursorIcon::Move => 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::Pointer),
egui::CursorIcon::Progress => Some(winit::window::CursorIcon::Progress),
egui::CursorIcon::ResizeHorizontal => Some(winit::window::CursorIcon::EwResize),
egui::CursorIcon::ResizeNeSw => Some(winit::window::CursorIcon::NeswResize),
egui::CursorIcon::ResizeNwSe => Some(winit::window::CursorIcon::NwseResize),
egui::CursorIcon::ResizeVertical => Some(winit::window::CursorIcon::NsResize),
egui::CursorIcon::ResizeEast => Some(winit::window::CursorIcon::EResize),
egui::CursorIcon::ResizeSouthEast => Some(winit::window::CursorIcon::SeResize),
egui::CursorIcon::ResizeSouth => Some(winit::window::CursorIcon::SResize),
egui::CursorIcon::ResizeSouthWest => Some(winit::window::CursorIcon::SwResize),
egui::CursorIcon::ResizeWest => Some(winit::window::CursorIcon::WResize),
egui::CursorIcon::ResizeNorthWest => Some(winit::window::CursorIcon::NwResize),
egui::CursorIcon::ResizeNorth => Some(winit::window::CursorIcon::NResize),
egui::CursorIcon::ResizeNorthEast => Some(winit::window::CursorIcon::NeResize),
egui::CursorIcon::ResizeColumn => Some(winit::window::CursorIcon::ColResize),
egui::CursorIcon::ResizeRow => Some(winit::window::CursorIcon::RowResize),
egui::CursorIcon::Text => Some(winit::window::CursorIcon::Text),
egui::CursorIcon::VerticalText => Some(winit::window::CursorIcon::VerticalText),
egui::CursorIcon::Wait => Some(winit::window::CursorIcon::Wait),
egui::CursorIcon::ZoomIn => Some(winit::window::CursorIcon::ZoomIn),
egui::CursorIcon::ZoomOut => Some(winit::window::CursorIcon::ZoomOut),
}
}
// Helpers for egui Viewports
// ---------------------------------------------------------------------------
#[derive(PartialEq, Eq, Hash, Debug)]
@@ -1383,7 +1357,7 @@ pub fn process_viewport_commands(
egui_ctx: &egui::Context,
info: &mut ViewportInfo,
commands: impl IntoIterator<Item = ViewportCommand>,
window: &Window,
window: &dyn Window,
actions_requested: &mut Vec<ActionRequested>,
) {
for command in commands {
@@ -1393,7 +1367,7 @@ pub fn process_viewport_commands(
fn process_viewport_command(
egui_ctx: &egui::Context,
window: &Window,
window: &dyn Window,
command: ViewportCommand,
info: &mut ViewportInfo,
actions_requested: &mut Vec<ActionRequested>,
@@ -1425,7 +1399,7 @@ fn process_viewport_command(
let width_px = pixels_per_point * size.x.max(1.0);
let height_px = pixels_per_point * size.y.max(1.0);
let requested_size = PhysicalSize::new(width_px, height_px);
if let Some(_returned_inner_size) = window.request_inner_size(requested_size) {
if let Some(_returned_inner_size) = window.request_surface_size(requested_size.into()) {
// On platforms where the size is entirely controlled by the user the
// applied size will be returned immediately, resize event in such case
// may not be generated.
@@ -1470,21 +1444,21 @@ fn process_viewport_command(
window.set_outer_position(PhysicalPosition::new(
pixels_per_point * pos.x,
pixels_per_point * pos.y,
));
).into());
}
ViewportCommand::MinInnerSize(s) => {
window.set_min_inner_size((s.is_finite() && s != Vec2::ZERO).then_some(
PhysicalSize::new(pixels_per_point * s.x, pixels_per_point * s.y),
window.set_min_surface_size((s.is_finite() && s != Vec2::ZERO).then_some(
PhysicalSize::new(pixels_per_point * s.x, pixels_per_point * s.y).into(),
));
}
ViewportCommand::MaxInnerSize(s) => {
window.set_max_inner_size((s.is_finite() && s != Vec2::INFINITY).then_some(
PhysicalSize::new(pixels_per_point * s.x, pixels_per_point * s.y),
window.set_max_surface_size((s.is_finite() && s != Vec2::INFINITY).then_some(
PhysicalSize::new(pixels_per_point * s.x, pixels_per_point * s.y).into(),
));
}
ViewportCommand::ResizeIncrements(s) => {
window.set_resize_increments(
s.map(|s| PhysicalSize::new(pixels_per_point * s.x, pixels_per_point * s.y)),
window.set_surface_resize_increments(
s.map(|s| PhysicalSize::new(pixels_per_point * s.x, pixels_per_point * s.y).into()),
);
}
ViewportCommand::Resizable(v) => window.set_resizable(v),
@@ -1516,7 +1490,7 @@ fn process_viewport_command(
info.maximized = Some(v);
}
ViewportCommand::Fullscreen(v) => {
window.set_fullscreen(v.then_some(winit::window::Fullscreen::Borderless(None)));
window.set_fullscreen(v.then_some(winit_core::monitor::Fullscreen::Borderless(None)));
}
ViewportCommand::Decorations(v) => window.set_decorations(v),
ViewportCommand::WindowLevel(l) => window.set_window_level(match l {
@@ -1530,11 +1504,11 @@ fn process_viewport_command(
}
ViewportCommand::IMERect(rect) => {
window.set_ime_cursor_area(
PhysicalPosition::new(pixels_per_point * rect.min.x, pixels_per_point * rect.min.y),
PhysicalPosition::new(pixels_per_point * rect.min.x, pixels_per_point * rect.min.y).into(),
PhysicalSize::new(
pixels_per_point * rect.size().x,
pixels_per_point * rect.size().y,
),
).into(),
);
}
ViewportCommand::IMEAllowed(v) => window.set_ime_allowed(v),
@@ -1569,7 +1543,7 @@ fn process_viewport_command(
if let Err(err) = window.set_cursor_position(PhysicalPosition::new(
pixels_per_point * pos.x,
pixels_per_point * pos.y,
)) {
).into()) {
log::warn!("{command:?}: {err}");
}
}
@@ -1611,14 +1585,14 @@ fn process_viewport_command(
/// Possible causes of error include denied permission, incompatible system, and lack of memory.
pub fn create_window(
egui_ctx: &egui::Context,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
viewport_builder: &ViewportBuilder,
) -> Result<Window, winit::error::OsError> {
) -> Result<Box<dyn Window>, winit::error::RequestError> {
profiling::function_scope!();
let window_attributes = create_winit_window_attributes(egui_ctx, viewport_builder.clone());
let window = event_loop.create_window(window_attributes)?;
apply_viewport_builder_to_window(egui_ctx, &window, viewport_builder);
apply_viewport_builder_to_window(egui_ctx, window.deref(), viewport_builder);
Ok(window)
}
@@ -1686,7 +1660,7 @@ pub fn create_winit_window_attributes(
egui::viewport::WindowLevel::Normal => WindowLevel::Normal,
})
.with_fullscreen(
fullscreen.and_then(|e| e.then_some(winit::window::Fullscreen::Borderless(None))),
fullscreen.and_then(|e| e.then_some(winit_core::monitor::Fullscreen::Borderless(None))),
)
.with_enabled_buttons({
let mut buttons = WindowButtons::empty();
@@ -1719,17 +1693,17 @@ pub fn create_winit_window_attributes(
if let Some(size) = inner_size {
window_attributes = window_attributes
.with_inner_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
.with_surface_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
}
if let Some(size) = min_inner_size {
window_attributes = window_attributes
.with_min_inner_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
.with_min_surface_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
}
if let Some(size) = max_inner_size {
window_attributes = window_attributes
.with_max_inner_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
.with_max_surface_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
}
if let Some(pos) = position {
@@ -1798,26 +1772,27 @@ pub fn create_winit_window_attributes(
#[cfg(target_os = "macos")]
{
use winit::platform::macos::WindowAttributesExtMacOS as _;
window_attributes = window_attributes
let mac_window_attributes = winit::platform::macos::WindowAttributesMacOS::default()
.with_title_hidden(!_title_shown.unwrap_or(true))
.with_titlebar_buttons_hidden(!_titlebar_buttons_shown.unwrap_or(true))
.with_titlebar_transparent(!_titlebar_shown.unwrap_or(true))
.with_fullsize_content_view(_fullsize_content_view.unwrap_or(false))
.with_movable_by_window_background(_movable_by_window_background.unwrap_or(false))
.with_has_shadow(_has_shadow.unwrap_or(true));
window_attributes =
window_attributes.with_platform_attributes(Box::new(mac_window_attributes));
}
window_attributes
}
fn to_winit_icon(icon: &egui::IconData) -> Option<winit::window::Icon> {
fn to_winit_icon(icon: &egui::IconData) -> Option<winit_core::icon::Icon> {
if icon.is_empty() {
None
} else {
profiling::function_scope!();
match winit::window::Icon::from_rgba(icon.rgba.clone(), icon.width, icon.height) {
Ok(winit_icon) => Some(winit_icon),
match winit_core::icon::RgbaIcon::new(icon.rgba.clone(), icon.width, icon.height) {
Ok(winit_icon) => Some(winit_icon.into()),
Err(err) => {
log::warn!("Invalid IconData: {err}");
None
@@ -1829,7 +1804,7 @@ fn to_winit_icon(icon: &egui::IconData) -> Option<winit::window::Icon> {
/// Applies what `create_winit_window_builder` couldn't
pub fn apply_viewport_builder_to_window(
egui_ctx: &egui::Context,
window: &Window,
window: &dyn Window,
builder: &ViewportBuilder,
) {
if let Some(mouse_passthrough) = builder.mouse_passthrough
@@ -1848,29 +1823,29 @@ pub fn apply_viewport_builder_to_window(
if let Some(size) = builder.inner_size
&& window
.request_inner_size(PhysicalSize::new(
.request_surface_size(PhysicalSize::new(
pixels_per_point * size.x,
pixels_per_point * size.y,
))
).into())
.is_some()
{
log::debug!("Failed to set window size");
}
if let Some(size) = builder.min_inner_size {
window.set_min_inner_size(Some(PhysicalSize::new(
window.set_min_surface_size(Some(PhysicalSize::new(
pixels_per_point * size.x,
pixels_per_point * size.y,
)));
).into()));
}
if let Some(size) = builder.max_inner_size {
window.set_max_inner_size(Some(PhysicalSize::new(
window.set_max_surface_size(Some(PhysicalSize::new(
pixels_per_point * size.x,
pixels_per_point * size.y,
)));
).into()));
}
if let Some(pos) = builder.position {
let pos = PhysicalPosition::new(pixels_per_point * pos.x, pixels_per_point * pos.y);
window.set_outer_position(pos);
window.set_outer_position(pos.into());
}
if let Some(maximized) = builder.maximized {
window.set_maximized(maximized);
@@ -1886,13 +1861,10 @@ pub fn short_device_event_description(event: &winit::event::DeviceEvent) -> &'st
use winit::event::DeviceEvent;
match event {
DeviceEvent::Added => "DeviceEvent::Added",
DeviceEvent::Removed => "DeviceEvent::Removed",
DeviceEvent::MouseMotion { .. } => "DeviceEvent::MouseMotion",
DeviceEvent::MouseWheel { .. } => "DeviceEvent::MouseWheel",
DeviceEvent::Motion { .. } => "DeviceEvent::Motion",
DeviceEvent::Button { .. } => "DeviceEvent::Button",
DeviceEvent::Key { .. } => "DeviceEvent::Key",
DeviceEvent::PointerMotion { .. } => "DeviceEvent::PointerMotion",
}
}
@@ -1903,32 +1875,31 @@ pub fn short_window_event_description(event: &winit::event::WindowEvent) -> &'st
match event {
WindowEvent::ActivationTokenDone { .. } => "WindowEvent::ActivationTokenDone",
WindowEvent::Resized { .. } => "WindowEvent::Resized",
WindowEvent::Moved { .. } => "WindowEvent::Moved",
WindowEvent::CloseRequested => "WindowEvent::CloseRequested",
WindowEvent::Destroyed => "WindowEvent::Destroyed",
WindowEvent::DroppedFile { .. } => "WindowEvent::DroppedFile",
WindowEvent::HoveredFile { .. } => "WindowEvent::HoveredFile",
WindowEvent::HoveredFileCancelled => "WindowEvent::HoveredFileCancelled",
WindowEvent::Focused { .. } => "WindowEvent::Focused",
WindowEvent::KeyboardInput { .. } => "WindowEvent::KeyboardInput",
WindowEvent::ModifiersChanged { .. } => "WindowEvent::ModifiersChanged",
WindowEvent::Ime { .. } => "WindowEvent::Ime",
WindowEvent::CursorMoved { .. } => "WindowEvent::CursorMoved",
WindowEvent::CursorEntered { .. } => "WindowEvent::CursorEntered",
WindowEvent::CursorLeft { .. } => "WindowEvent::CursorLeft",
WindowEvent::MouseWheel { .. } => "WindowEvent::MouseWheel",
WindowEvent::MouseInput { .. } => "WindowEvent::MouseInput",
WindowEvent::PinchGesture { .. } => "WindowEvent::PinchGesture",
WindowEvent::RedrawRequested => "WindowEvent::RedrawRequested",
WindowEvent::DoubleTapGesture { .. } => "WindowEvent::DoubleTapGesture",
WindowEvent::RotationGesture { .. } => "WindowEvent::RotationGesture",
WindowEvent::TouchpadPressure { .. } => "WindowEvent::TouchpadPressure",
WindowEvent::AxisMotion { .. } => "WindowEvent::AxisMotion",
WindowEvent::Touch { .. } => "WindowEvent::Touch",
WindowEvent::ScaleFactorChanged { .. } => "WindowEvent::ScaleFactorChanged",
WindowEvent::ThemeChanged { .. } => "WindowEvent::ThemeChanged",
WindowEvent::Occluded { .. } => "WindowEvent::Occluded",
WindowEvent::PanGesture { .. } => "WindowEvent::PanGesture",
WindowEvent::SurfaceResized(_) => "WindowEvent::SurfaceResized",
WindowEvent::DragEntered { .. } => "WindowEvent::DragEntered",
WindowEvent::DragMoved { .. } => "WindowEvent::DragMoved",
WindowEvent::DragDropped { .. } => "WindowEvent::DragDropped",
WindowEvent::DragLeft { .. } => "WindowEvent::DragLeft",
WindowEvent::PointerMoved { .. } => "WindowEvent::PointerMoved",
WindowEvent::PointerEntered { .. } => "WindowEvent::PointerEntered",
WindowEvent::PointerLeft { .. } => "WindowEvent::PointerLeft",
WindowEvent::PointerButton { .. } => "WindowEvent::PointerButton",
}
}

View File

@@ -6,7 +6,7 @@ use egui::ViewportBuilder;
#[cfg_attr(feature = "serde", serde(default))]
pub struct WindowSettings {
/// Position of window content in physical pixels.
inner_position_pixels: Option<egui::Pos2>,
inner_position_pixels: egui::Pos2,
/// Position of window frame/titlebar in physical pixels.
outer_position_pixels: Option<egui::Pos2>,
@@ -20,15 +20,13 @@ pub struct WindowSettings {
}
impl WindowSettings {
pub fn from_window(egui_zoom_factor: f32, window: &winit::window::Window) -> Self {
pub fn from_window(egui_zoom_factor: f32, window: &dyn winit::window::Window) -> Self {
let inner_size_points = window
.inner_size()
.surface_size()
.to_logical::<f32>(egui_zoom_factor as f64 * window.scale_factor());
let inner_position_pixels = window
.inner_position()
.ok()
.map(|p| egui::pos2(p.x as f32, p.y as f32));
let inner_position = window.surface_position();
let inner_position_pixels = egui::pos2(inner_position.x as f32, inner_position.y as f32);
let outer_position_pixels = window
.outer_position()
@@ -56,7 +54,7 @@ impl WindowSettings {
pub fn initialize_viewport_builder(
&self,
egui_zoom_factor: f32,
event_loop: &winit::event_loop::ActiveEventLoop,
event_loop: &dyn winit::event_loop::ActiveEventLoop,
mut viewport_builder: ViewportBuilder,
) -> ViewportBuilder {
profiling::function_scope!();
@@ -64,7 +62,7 @@ impl WindowSettings {
// `WindowBuilder::with_position` expects inner position in Macos, and outer position elsewhere
// See [`winit::window::WindowBuilder::with_position`] for details.
let pos_px = if cfg!(target_os = "macos") {
self.inner_position_pixels
Some(self.inner_position_pixels)
} else {
self.outer_position_pixels
};
@@ -90,12 +88,12 @@ impl WindowSettings {
viewport_builder
}
pub fn initialize_window(&self, window: &winit::window::Window) {
pub fn initialize_window(&self, window: &dyn winit::window::Window) {
if cfg!(target_os = "macos") {
// Mac sometimes has problems restoring the window to secondary monitors
// using only `WindowBuilder::with_position`, so we need this extra step:
if let Some(pos) = self.outer_position_pixels {
window.set_outer_position(winit::dpi::PhysicalPosition { x: pos.x, y: pos.y });
window.set_outer_position(dpi::PhysicalPosition { x: pos.x, y: pos.y }.into());
}
}
}
@@ -117,7 +115,7 @@ impl WindowSettings {
pub fn clamp_position_to_monitors(
&mut self,
egui_zoom_factor: f32,
event_loop: &winit::event_loop::ActiveEventLoop,
event_loop: &dyn winit::event_loop::ActiveEventLoop,
) {
// If the app last ran on two monitors and only one is now connected, then
// the given position is invalid.
@@ -132,9 +130,12 @@ impl WindowSettings {
return;
};
if let Some(pos_px) = &mut self.inner_position_pixels {
clamp_pos_to_monitors(egui_zoom_factor, event_loop, inner_size_points, pos_px);
}
clamp_pos_to_monitors(
egui_zoom_factor,
event_loop,
inner_size_points,
&mut self.inner_position_pixels,
);
if let Some(pos_px) = &mut self.outer_position_pixels {
clamp_pos_to_monitors(egui_zoom_factor, event_loop, inner_size_points, pos_px);
}
@@ -143,74 +144,75 @@ impl WindowSettings {
fn find_active_monitor(
egui_zoom_factor: f32,
event_loop: &winit::event_loop::ActiveEventLoop,
event_loop: &dyn winit::event_loop::ActiveEventLoop,
window_size_pts: egui::Vec2,
position_px: &egui::Pos2,
) -> Option<winit::monitor::MonitorHandle> {
profiling::function_scope!();
let monitors = event_loop.available_monitors();
// default to primary monitor, in case the correct monitor was disconnected.
let Some(mut active_monitor) = event_loop
.primary_monitor()
.or_else(|| event_loop.available_monitors().next())
else {
return None; // no monitors 🤷
};
for monitor in monitors {
let window_size_px = window_size_pts * (egui_zoom_factor * monitor.scale_factor() as f32);
let monitor_x_range = (monitor.position().x - window_size_px.x as i32)
..(monitor.position().x + monitor.size().width as i32);
let monitor_y_range = (monitor.position().y - window_size_px.y as i32)
..(monitor.position().y + monitor.size().height as i32);
if monitor_x_range.contains(&(position_px.x as i32))
&& monitor_y_range.contains(&(position_px.y as i32))
{
active_monitor = monitor;
}
}
Some(active_monitor)
None // TODO
// profiling::function_scope!();
// let monitors = event_loop.available_monitors();
//
// // default to primary monitor, in case the correct monitor was disconnected.
// let Some(mut active_monitor) = event_loop
// .primary_monitor()
// .or_else(|| event_loop.available_monitors().next())
// else {
// return None; // no monitors 🤷
// };
//
// for monitor in monitors {
// let window_size_px = window_size_pts * (egui_zoom_factor * monitor.scale_factor() as f32);
// let monitor_x_range = (monitor.position().x - window_size_px.x as i32)
// ..(monitor.position().x + monitor.size().width as i32);
// let monitor_y_range = (monitor.position().y - window_size_px.y as i32)
// ..(monitor.position().y + monitor.size().height as i32);
//
// if monitor_x_range.contains(&(position_px.x as i32))
// && monitor_y_range.contains(&(position_px.y as i32))
// {
// active_monitor = monitor;
// }
// }
//
// Some(active_monitor)
}
fn clamp_pos_to_monitors(
egui_zoom_factor: f32,
event_loop: &winit::event_loop::ActiveEventLoop,
event_loop: &dyn winit::event_loop::ActiveEventLoop,
window_size_pts: egui::Vec2,
position_px: &mut egui::Pos2,
) {
profiling::function_scope!();
let Some(active_monitor) =
find_active_monitor(egui_zoom_factor, event_loop, window_size_pts, position_px)
else {
return; // no monitors 🤷
};
let mut window_size_px =
window_size_pts * (egui_zoom_factor * active_monitor.scale_factor() as f32);
// Add size of title bar. This is 32 px by default in Win 10/11.
if cfg!(target_os = "windows") {
window_size_px += egui::Vec2::new(
0.0,
32.0 * egui_zoom_factor * active_monitor.scale_factor() as f32,
);
}
let monitor_position = egui::Pos2::new(
active_monitor.position().x as f32,
active_monitor.position().y as f32,
);
let monitor_size_px = egui::Vec2::new(
active_monitor.size().width as f32,
active_monitor.size().height as f32,
);
// Window size cannot be negative or the subsequent `clamp` will panic.
let window_size = (monitor_size_px - window_size_px).max(egui::Vec2::ZERO);
// To get the maximum position, we get the rightmost corner of the display, then
// subtract the size of the window to get the bottom right most value window.position
// can have.
*position_px = position_px.clamp(monitor_position, monitor_position + window_size);
// profiling::function_scope!();
//
// let Some(active_monitor) =
// find_active_monitor(egui_zoom_factor, event_loop, window_size_pts, position_px)
// else {
// return; // no monitors 🤷
// };
//
// let mut window_size_px =
// window_size_pts * (egui_zoom_factor * active_monitor.scale_factor() as f32);
// // Add size of title bar. This is 32 px by default in Win 10/11.
// if cfg!(target_os = "windows") {
// window_size_px += egui::Vec2::new(
// 0.0,
// 32.0 * egui_zoom_factor * active_monitor.scale_factor() as f32,
// );
// }
// let monitor_position = egui::Pos2::new(
// active_monitor.position().x as f32,
// active_monitor.position().y as f32,
// );
// let monitor_size_px = egui::Vec2::new(
// active_monitor.size().width as f32,
// active_monitor.size().height as f32,
// );
//
// // Window size cannot be negative or the subsequent `clamp` will panic.
// let window_size = (monitor_size_px - window_size_px).max(egui::Vec2::ZERO);
// // To get the maximum position, we get the rightmost corner of the display, then
// // subtract the size of the window to get the bottom right most value window.position
// // can have.
// *position_px = position_px.clamp(monitor_position, monitor_position + window_size);
}

View File

@@ -61,7 +61,7 @@ persistence = ["serde", "epaint/serde", "ron"]
rayon = ["epaint/rayon"]
## Allow serialization using [`serde`](https://docs.rs/serde).
serde = ["dep:serde", "epaint/serde", "accesskit?/serde"]
serde = ["dep:serde", "epaint/serde", "accesskit?/serde", "cursor-icon/serde"]
## Change Vertex layout to be compatible with unity
unity = ["epaint/unity"]
@@ -77,6 +77,7 @@ epaint = { workspace = true, default-features = false }
ahash.workspace = true
bitflags.workspace = true
cursor-icon.workspace = true
log.workspace = true
nohash-hasher.workspace = true
profiling.workspace = true

View File

@@ -846,28 +846,28 @@ impl Panel {
if panel_sizer.size <= self.size_range.min {
match self.side {
PanelSide::Vertical(side) => match side {
VerticalSide::Left => CursorIcon::ResizeEast,
VerticalSide::Right => CursorIcon::ResizeWest,
VerticalSide::Left => CursorIcon::EResize,
VerticalSide::Right => CursorIcon::WResize,
},
PanelSide::Horizontal(side) => match side {
HorizontalSide::Top => CursorIcon::ResizeSouth,
HorizontalSide::Bottom => CursorIcon::ResizeNorth,
HorizontalSide::Top => CursorIcon::SResize,
HorizontalSide::Bottom => CursorIcon::NResize,
},
}
} else if panel_sizer.size < self.size_range.max {
match self.side {
PanelSide::Vertical(_) => CursorIcon::ResizeHorizontal,
PanelSide::Horizontal(_) => CursorIcon::ResizeVertical,
PanelSide::Vertical(_) => CursorIcon::ColResize,
PanelSide::Horizontal(_) => CursorIcon::RowResize,
}
} else {
match self.side {
PanelSide::Vertical(side) => match side {
VerticalSide::Left => CursorIcon::ResizeWest,
VerticalSide::Right => CursorIcon::ResizeEast,
VerticalSide::Left => CursorIcon::WResize,
VerticalSide::Right => CursorIcon::EResize,
},
PanelSide::Horizontal(side) => match side {
HorizontalSide::Top => CursorIcon::ResizeNorth,
HorizontalSide::Bottom => CursorIcon::ResizeSouth,
HorizontalSide::Top => CursorIcon::NResize,
HorizontalSide::Bottom => CursorIcon::SResize,
},
}
}

View File

@@ -362,7 +362,7 @@ impl Resize {
paint_resize_corner(ui, &corner_response);
if corner_response.hovered() || corner_response.dragged() {
ui.ctx().set_cursor_icon(CursorIcon::ResizeNwSe);
ui.ctx().set_cursor_icon(CursorIcon::NwseResize);
}
}

View File

@@ -798,13 +798,13 @@ impl ResizeInteraction {
// TODO(emilk): use one-sided cursors for when we reached the min/max size.
if (left && top) || (right && bottom) {
ctx.set_cursor_icon(CursorIcon::ResizeNwSe);
ctx.set_cursor_icon(CursorIcon::NwseResize);
} else if (right && top) || (left && bottom) {
ctx.set_cursor_icon(CursorIcon::ResizeNeSw);
ctx.set_cursor_icon(CursorIcon::NwseResize);
} else if left || right {
ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
ctx.set_cursor_icon(CursorIcon::ColResize);
} else if bottom || top {
ctx.set_cursor_icon(CursorIcon::ResizeVertical);
ctx.set_cursor_icon(CursorIcon::RowResize);
}
}

View File

@@ -261,174 +261,46 @@ pub enum UserAttentionType {
Reset,
}
/// A mouse cursor icon.
///
/// egui emits a [`CursorIcon`] in [`PlatformOutput`] each frame as a request to the integration.
///
/// Loosely based on <https://developer.mozilla.org/en-US/docs/Web/CSS/cursor>.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum CursorIcon {
/// Normal cursor icon, whatever that is.
#[default]
Default,
pub use cursor_icon::CursorIcon;
/// Show no cursor
None,
// ------------------------------------
// Links and status:
/// A context menu is available
ContextMenu,
/// Question mark
Help,
/// Pointing hand, used for e.g. web links
PointingHand,
/// Shows that processing is being done, but that the program is still interactive.
Progress,
/// Not yet ready, try later.
Wait,
// ------------------------------------
// Selection:
/// Hover a cell in a table
Cell,
/// For precision work
Crosshair,
/// Text caret, e.g. "Click here to edit text"
Text,
/// Vertical text caret, e.g. "Click here to edit vertical text"
VerticalText,
// ------------------------------------
// Drag-and-drop:
/// Indicated an alias, e.g. a shortcut
Alias,
/// Indicate that a copy will be made
Copy,
/// Omnidirectional move icon (e.g. arrows in all cardinal directions)
Move,
/// Can't drop here
NoDrop,
/// Forbidden
NotAllowed,
/// The thing you are hovering can be grabbed
Grab,
/// You are grabbing the thing you are hovering
Grabbing,
// ------------------------------------
/// Something can be scrolled in any direction (panned).
AllScroll,
// ------------------------------------
// Resizing in two directions:
/// Horizontal resize `-` to make something wider or more narrow (left to/from right)
ResizeHorizontal,
/// Diagonal resize `/` (right-up to/from left-down)
ResizeNeSw,
/// Diagonal resize `\` (left-up to/from right-down)
ResizeNwSe,
/// Vertical resize `|` (up-down or down-up)
ResizeVertical,
// ------------------------------------
// Resizing in one direction:
/// Resize something rightwards (e.g. when dragging the right-most edge of something)
ResizeEast,
/// Resize something down and right (e.g. when dragging the bottom-right corner of something)
ResizeSouthEast,
/// Resize something downwards (e.g. when dragging the bottom edge of something)
ResizeSouth,
/// Resize something down and left (e.g. when dragging the bottom-left corner of something)
ResizeSouthWest,
/// Resize something leftwards (e.g. when dragging the left edge of something)
ResizeWest,
/// Resize something up and left (e.g. when dragging the top-left corner of something)
ResizeNorthWest,
/// Resize something up (e.g. when dragging the top edge of something)
ResizeNorth,
/// Resize something up and right (e.g. when dragging the top-right corner of something)
ResizeNorthEast,
// ------------------------------------
/// Resize a column
ResizeColumn,
/// Resize a row
ResizeRow,
// ------------------------------------
// Zooming:
/// Enhance!
ZoomIn,
/// Let's get a better overview
ZoomOut,
}
impl CursorIcon {
pub const ALL: [Self; 35] = [
Self::Default,
Self::None,
Self::ContextMenu,
Self::Help,
Self::PointingHand,
Self::Progress,
Self::Wait,
Self::Cell,
Self::Crosshair,
Self::Text,
Self::VerticalText,
Self::Alias,
Self::Copy,
Self::Move,
Self::NoDrop,
Self::NotAllowed,
Self::Grab,
Self::Grabbing,
Self::AllScroll,
Self::ResizeHorizontal,
Self::ResizeNeSw,
Self::ResizeNwSe,
Self::ResizeVertical,
Self::ResizeEast,
Self::ResizeSouthEast,
Self::ResizeSouth,
Self::ResizeSouthWest,
Self::ResizeWest,
Self::ResizeNorthWest,
Self::ResizeNorth,
Self::ResizeNorthEast,
Self::ResizeColumn,
Self::ResizeRow,
Self::ZoomIn,
Self::ZoomOut,
];
}
pub const ALL_CURSOR_ICONS: [CursorIcon; 36] = [
CursorIcon::Default,
CursorIcon::ContextMenu,
CursorIcon::Help,
CursorIcon::Pointer,
CursorIcon::Progress,
CursorIcon::Wait,
CursorIcon::Cell,
CursorIcon::Crosshair,
CursorIcon::Text,
CursorIcon::VerticalText,
CursorIcon::Alias,
CursorIcon::Copy,
CursorIcon::Move,
CursorIcon::NoDrop,
CursorIcon::NotAllowed,
CursorIcon::Grab,
CursorIcon::Grabbing,
CursorIcon::EResize,
CursorIcon::NResize,
CursorIcon::NeResize,
CursorIcon::NwResize,
CursorIcon::SResize,
CursorIcon::SeResize,
CursorIcon::SwResize,
CursorIcon::WResize,
CursorIcon::EwResize,
CursorIcon::NsResize,
CursorIcon::NeswResize,
CursorIcon::NwseResize,
CursorIcon::ColResize,
CursorIcon::RowResize,
CursorIcon::AllScroll,
CursorIcon::ZoomIn,
CursorIcon::ZoomOut,
CursorIcon::DndAsk,
CursorIcon::AllResize,
];
/// Things that happened during this frame that the integration may be interested in.
///

View File

@@ -6,13 +6,7 @@ use emath::Align;
use epaint::{AlphaFromCoverage, CornerRadius, Shadow, Stroke, text::FontTweak};
use std::{collections::BTreeMap, ops::RangeInclusive, sync::Arc};
use crate::{
ComboBox, CursorIcon, FontFamily, FontId, Grid, Margin, Response, RichText, TextWrapMode,
WidgetText,
ecolor::Color32,
emath::{Rangef, Rect, Vec2, pos2, vec2},
reset_button_with,
};
use crate::{ComboBox, CursorIcon, FontFamily, FontId, Grid, Margin, Response, RichText, TextWrapMode, WidgetText, ecolor::Color32, emath::{Rangef, Rect, Vec2, pos2, vec2}, reset_button_with, output};
/// How to format numbers in e.g. a [`crate::DragValue`].
#[derive(Clone)]
@@ -2335,7 +2329,7 @@ impl Visuals {
.show_ui(ui, |ui| {
ui.selectable_value(interact_cursor, None, "-");
for cursor in CursorIcon::ALL {
for cursor in output::ALL_CURSOR_ICONS {
ui.selectable_value(interact_cursor, Some(cursor), format!("{cursor:?}"))
.on_hover_cursor(cursor);
}

View File

@@ -601,11 +601,11 @@ impl Widget for DragValue<'_> {
.min_size(ui.spacing().interact_size); // TODO(emilk): find some more generic solution to `min_size`
let cursor_icon = if value <= *range.start() {
CursorIcon::ResizeEast
CursorIcon::EResize
} else if value < *range.end() {
CursorIcon::ResizeHorizontal
CursorIcon::RowResize
} else {
CursorIcon::ResizeWest
CursorIcon::WResize
};
let response = ui.add(button);

View File

@@ -65,7 +65,7 @@ impl Widget for Link {
}
if response.hovered() {
ui.ctx().set_cursor_icon(CursorIcon::PointingHand);
ui.ctx().set_cursor_icon(CursorIcon::Pointer);
}
}

View File

@@ -58,7 +58,7 @@ profiling.workspace = true
document-features = { workspace = true, optional = true }
# Native:
winit = { workspace = true, optional = true, default-features = false, features = ["rwh_06"] }
winit = { workspace = true, optional = true, default-features = false }
# Web:
[target.'cfg(target_arch = "wasm32")'.dependencies]

View File

@@ -13,7 +13,7 @@ workspace = true
[dependencies]
eframe = { workspace = true, features = [
"default",
"wgpu",
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
] }
env_logger = { workspace = true, features = ["auto-color", "humantime"] }