diff --git a/crates/ui-egui/src/screen_picker.rs b/crates/ui-egui/src/screen_picker.rs index 865f6537d1..b9c163d3f8 100644 --- a/crates/ui-egui/src/screen_picker.rs +++ b/crates/ui-egui/src/screen_picker.rs @@ -259,7 +259,9 @@ fn viewport_builder(ctx: &Context, image: &ScreenImage) -> egui::ViewportBuilder .with_resizable(false) .with_position(image.position / ctx.zoom_factor()) .with_inner_size(image.size / ctx.zoom_factor()) - .with_window_level(egui::WindowLevel::AlwaysOnTop) + // Not `AlwaysOnTop` here: a monitor-sized window created topmost makes the DX12 backend + // fail its swapchain creation (0x887A0001) and the app panics. The level is raised once + // the first frame has been painted, in `show`. // Do not expose the native window's empty first frame over the desktop. // The viewport is made visible after its snapshot has been painted below. .with_visible(false) @@ -280,7 +282,10 @@ pub fn show(ctx: &Context) { let shared = r.clone(); let vid = egui::ViewportId::from_hash_of(("screen-color", generation, n)); let builder = viewport_builder(ctx, &image); - ctx.show_viewport_deferred(vid, builder, move |ui, _| { + // Immediate, so it paints inside the main window's own frame: as a deferred viewport the + // main window stopped being redrawn on Windows (OpenGL) once the picker was up, so a click + // or Esc was never turned into an answer and the overlay could not be left. + ctx.show_viewport_immediate(vid, builder, move |ui, _| { { let s = lock(&shared); if s.generation != generation || s.owner.is_none() { @@ -334,6 +339,11 @@ pub fn show(ctx: &Context) { // Showing a new native viewport before this frame is painted can briefly cover // the screen with the window's default white clear color. ui.ctx().send_viewport_cmd(egui::ViewportCommand::Visible(true)); + // Once per picker window: `show` runs every frame, so a local flag would resend it. + let raised = Id::new(("screen-picker-raised", ui.ctx().viewport_id())); + if !ui.ctx().data_mut(|d| std::mem::replace(d.get_temp_mut_or_default::(raised), true)) { + ui.ctx().send_viewport_cmd(egui::ViewportCommand::WindowLevel(egui::WindowLevel::AlwaysOnTop)); + } }); } } @@ -393,6 +403,12 @@ mod tests { assert_eq!(builder.visible, Some(false)); } #[test] + fn screen_picker_viewport_is_not_created_always_on_top() { + // Creating the monitor-sized window topmost fails DX12 swapchain creation (Windows). + let builder = viewport_builder(&Context::default(), &image()); + assert_eq!(builder.window_level, None); + } + #[test] fn pixel_mapping_handles_display_edges_negative_origins_and_hidpi() { let i = image(); let rect = Rect::from_min_size(i.position, i.size);