From 7aa7f848581e57c74cccff5fcb48bd3bd48b8f28 Mon Sep 17 00:00:00 2001 From: rustbasic <127506429+rustbasic@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:49:33 +0900 Subject: [PATCH] Fix transparent child viewports on `Windows` with `glow` (#8423) Fix transparent child viewports on `Windows` with `glow` * Closes #3632 * Related #4451 * Related #5072 * Closes #7543 * Related #8116 Transparent native child viewports could become opaque on Windows when the selected GL config reports that it does not support transparency. `glutin_winit::finalize_window` clears the native transparent window attribute in that case. However, on affected Windows GL paths, transparent native windows and their GL surfaces still composite correctly. This change preserves the transparent window attribute for explicitly transparent non-root viewports on Windows by creating those windows directly. Tested manually on Windows with glow: - root transparent viewport - deferred native child viewport - immediate native child viewport --- crates/eframe/src/native/glow_integration.rs | 31 ++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index cca1d22c6..28a1ee681 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -1268,11 +1268,30 @@ impl GlutinWindowContext { ); if window_attributes.transparent() && self.gl_config.supports_transparency() == Some(false) + && !cfg!(target_os = "windows") { log::error!("Cannot create transparent window: the GL config does not support it"); } - let window = - glutin_winit::finalize_window(event_loop, window_attributes, &self.gl_config)?; + + let window = cfg_select! { + target_os = "windows" => { + if viewport_id != ViewportId::ROOT && window_attributes.transparent() { + // Preserve explicitly requested transparent child viewports on Windows. + // Some GL paths report no transparency support although composition works. + event_loop.create_window(window_attributes)? + } else { + glutin_winit::finalize_window( + event_loop, + window_attributes, + &self.gl_config, + )? + } + } + _ => { + // Keep the normal platform-specific finalization path elsewhere. + glutin_winit::finalize_window(event_loop, window_attributes, &self.gl_config)? + } + }; egui_winit::apply_viewport_builder_to_window( &self.egui_ctx, &window, @@ -1497,9 +1516,17 @@ fn initialize_or_update_viewport( .and_then(|vp| vp.builder.icon.clone()); } + let root_transparent = viewports + .get(&ViewportId::ROOT) + .and_then(|viewport| viewport.builder.transparent); + match viewports.entry(ids.this) { Entry::Vacant(entry) => { // New viewport: + if ids.this != ViewportId::ROOT && builder.transparent.is_none() { + // Child viewports inherit the root setting unless they explicitly override it. + builder.transparent = root_transparent; + } log::debug!("Creating new viewport {:?} ({:?})", ids.this, builder.title); entry.insert(Viewport { ids,