Spawning `Window`s partially fails when there is no inital `PrimaryWindow`
Bevy version and features
- Still applies as of
maine2b2f4aea814662ffd3c
Relevant system information
This is on wayland.
AdapterInfo { name: "Apple M2 (G14G B0)", vendor: 65541, device: 0, device_type: IntegratedGpu, driver: "Honeykrisp", driver_info: "Mesa 26.0.0-devel (git-ad2f112ac2)", backend: Vulkan }
What you did
I am trying to create windows dynamically, and there is no meaning in having an initial window in my app, so I tried to disable it.
To have a simple reproducer, let's take the code from examples/window/multiple_windows.rs, and apply the following change:
diff --git ./examples/window/multiple_windows.rs ./examples/window/multiple_windows.rs
index 46d4a708a5a04eb35de8..dcb7a42a33f8d20b6a48 100644
--- ./examples/window/multiple_windows.rs
+++ ./examples/window/multiple_windows.rs
@@ -5,7 +5,10 @@
fn main() {
App::new()
// By default, a primary window gets spawned by `WindowPlugin`, contained in `DefaultPlugins`
- .add_plugins(DefaultPlugins)
+ .add_plugins(DefaultPlugins.set(WindowPlugin {
+ primary_window: None,
+ ..default()
+ }))
.add_systems(Startup, setup_scene)
.run();
}
The intent being that this would stop the primary window from being created, while the second window continues to be created a few lines below, and the end result is that exactly one window appears, and it's the second one.
What went wrong
Instead, no window appears, but the app keeps running, presumably because the condition of "is there any window left open applies, meaning that the window was created enough for that, but not enough to be visible.
Additional information
A workaround that works is to let the default window get created (by not overriding primary_window), and then immediately close it at startup:
app.add_systems(Startup, close_primary_window);
fn close_primary_window(
mut commands: Commands,
primary_window: Single<Entity, With<PrimaryWindow>>,
) {
commands.entity(*primary_window).despawn();
}
log with `WAYLAND_DEBUG=1`
Running `target/debug/examples/multiple_windows`
[2m2025-11-26T14:29:22.163283Z[0m [32m INFO[0m [2mbevy_diagnostic::system_information_diagnostics_plugin::internal[0m[2m:[0m SystemInfo { os: "Linux (Fedora Linux Asahi Remix 42)", kernel: "6.16.8-400.asahi.fc42.aarch64+16k", cpu: "Blizzard-M2", core_count: "8", memory: "23.0 GiB" }
[ 955397.608] -> wl_display#1.get_registry(new id wl_registry#2)
[ 955397.627] -> wl_display#1.sync(new id wl_callback#3)
[ 955397.675] {Display Queue} wl_display#1.delete_id(3)
[ 955397.682] wl_registry#2.global(1, "wl_shm", 2)
[ 955397.702] wl_registry#2.global(2, "zwp_linux_dmabuf_v1", 4)
[ 955397.708] wl_registry#2.global(3, "wl_compositor", 6)
[ 955397.712] wl_registry#2.global(4, "wl_subcompositor", 1)
[ 955397.717] wl_registry#2.global(5, "wl_data_device_manager", 3)
[ 955397.722] wl_registry#2.global(6, "zwlr_gamma_control_manager_v1", 1)
[ 955397.726] wl_registry#2.global(7, "zxdg_output_manager_v1", 3)
[ 955397.730] wl_registry#2.global(8, "ext_idle_notifier_v1", 1)
[ 955397.734] wl_registry#2.global(9, "zwp_idle_inhibit_manager_v1", 1)
[ 955397.739] wl_registry#2.global(10, "zwlr_layer_shell_v1", 4)
[ 955397.743] wl_registry#2.global(11, "xdg_wm_base", 5)
[ 955397.747] wl_registry#2.global(12, "zwp_tablet_manager_v2", 1)
[ 955397.751] wl_registry#2.global(13, "org_kde_kwin_server_decoration_manager", 1)
[ 955397.755] wl_registry#2.global(14, "zxdg_decoration_manager_v1", 1)
[ 955397.759] wl_registry#2.global(15, "zwp_relative_pointer_manager_v1", 1)
[ 955397.763] wl_registry#2.global(16, "zwp_pointer_constraints_v1", 1)
[ 955397.767] wl_registry#2.global(17, "wp_presentation", 1)
[ 955397.772] wl_registry#2.global(18, "wp_alpha_modifier_v1", 1)
[ 955397.776] wl_registry#2.global(19, "zwlr_output_manager_v1", 4)
[ 955397.780] wl_registry#2.global(20, "zwlr_output_power_manager_v1", 1)
[ 955397.784] wl_registry#2.global(21, "zwp_input_method_manager_v2", 1)
[ 955397.789] wl_registry#2.global(22, "zwp_text_input_manager_v3", 1)
[ 955397.793] wl_registry#2.global(23, "ext_foreign_toplevel_list_v1", 1)
[ 955397.797] wl_registry#2.global(24, "zwlr_foreign_toplevel_manager_v1", 3)
[ 955397.802] wl_registry#2.global(25, "ext_session_lock_manager_v1", 1)
[ 955397.805] wl_registry#2.global(26, "wp_drm_lease_device_v1", 1)
[ 955397.810] wl_registry#2.global(27, "zwlr_export_dmabuf_manager_v1", 1)
[ 955397.814] wl_registry#2.global(28, "zwlr_screencopy_manager_v1", 3)
[ 955397.819] wl_registry#2.global(29, "zwlr_data_control_manager_v1", 2)
[ 955397.823] wl_registry#2.global(30, "wp_security_context_manager_v1", 1)
[ 955397.827] wl_registry#2.global(31, "wp_viewporter", 1)
[ 955397.831] wl_registry#2.global(32, "wp_single_pixel_buffer_manager_v1", 1)
[ 955397.836] wl_registry#2.global(33, "wp_content_type_manager_v1", 1)
[ 955397.840] wl_registry#2.global(34, "wp_fractional_scale_manager_v1", 1)
[ 955397.844] wl_registry#2.global(35, "wp_tearing_control_manager_v1", 1)
[ 955397.848] wl_registry#2.global(36, "zxdg_exporter_v1", 1)
[ 955397.852] wl_registry#2.global(37, "zxdg_importer_v1", 1)
[ 955397.856] wl_registry#2.global(38, "zxdg_exporter_v2", 1)
[ 955397.860] wl_registry#2.global(39, "zxdg_importer_v2", 1)
[ 955397.864] wl_registry#2.global(40, "xdg_activation_v1", 1)
[ 955397.868] wl_registry#2.global(41, "wp_cursor_shape_manager_v1", 1)
[ 955397.872] wl_registry#2.global(42, "zwp_virtual_keyboard_manager_v1", 1)
[ 955397.876] wl_registry#2.global(43, "zwlr_virtual_pointer_manager_v1", 2)
[ 955397.880] wl_registry#2.global(44, "zwp_keyboard_shortcuts_inhibit_manager_v1", 1)
[ 955397.884] wl_registry#2.global(45, "zwp_pointer_gestures_v1", 3)
[ 955397.888] wl_registry#2.global(46, "ext_transient_seat_manager_v1", 1)
[ 955397.892] wl_registry#2.global(47, "wl_seat", 9)
[ 955397.896] wl_registry#2.global(49, "zwp_primary_selection_device_manager_v1", 1)
[ 955397.900] wl_registry#2.global(50, "wl_output", 4)
[ 955397.904] wl_callback#3.done(150854)
[ 955397.944] -> wl_registry#2.bind(3, "wl_compositor", 6, new id [unknown]#3)
[ 955397.962] -> wl_registry#2.bind(4, "wl_subcompositor", 1, new id [unknown]#4)
[ 955397.974] -> wl_registry#2.bind(50, "wl_output", 4, new id [unknown]#5)
[ 955397.988] -> wl_registry#2.bind(7, "zxdg_output_manager_v1", 3, new id [unknown]#6)
[ 955398.004] -> zxdg_output_manager_v1#6.get_xdg_output(new id zxdg_output_v1#7, wl_output#5)
[ 955398.020] -> wl_registry#2.bind(47, "wl_seat", 7, new id [unknown]#8)
[ 955398.044] -> wl_registry#2.bind(34, "wp_fractional_scale_manager_v1", 1, new id [unknown]#9)
[ 955398.054] -> wl_registry#2.bind(31, "wp_viewporter", 1, new id [unknown]#10)
[ 955398.062] -> wl_registry#2.bind(1, "wl_shm", 1, new id [unknown]#11)
[ 955398.085] -> wl_shm#11.create_pool(new id wl_shm_pool#12, fd 8, 2)
[ 955398.101] -> wl_registry#2.bind(11, "xdg_wm_base", 5, new id [unknown]#13)
[ 955398.108] -> wl_registry#2.bind(14, "zxdg_decoration_manager_v1", 1, new id [unknown]#14)
[ 955398.115] -> wl_registry#2.bind(40, "xdg_activation_v1", 1, new id [unknown]#15)
[ 955398.126] -> wl_registry#2.bind(22, "zwp_text_input_manager_v3", 1, new id [unknown]#16)
[ 955398.137] -> wl_registry#2.bind(15, "zwp_relative_pointer_manager_v1", 1, new id [unknown]#17)
[ 955398.144] -> wl_registry#2.bind(16, "zwp_pointer_constraints_v1", 1, new id [unknown]#18)
[ 955398.151] -> wl_display#1.sync(new id wl_callback#19)
[ 955398.210] {Display Queue} wl_display#1.delete_id(19)
[ 955398.214] wl_output#5.geometry(0, 0, 290, 181, 0, "Unknown", "Unknown", 0)
[ 955398.220] wl_output#5.mode(1, 2560, 1600, 60000)
[ 955398.224] wl_output#5.scale(1)
[ 955398.227] wl_output#5.name("eDP-1")
[ 955398.230] wl_output#5.description("(null) (null) (eDP-1)")
[ 955398.233] wl_output#5.done()
[ 955398.236] zxdg_output_v1#7.name("eDP-1")
[ 955398.240] zxdg_output_v1#7.description("(null) (null) (eDP-1)")
[ 955398.242] zxdg_output_v1#7.logical_position(0, 0)
[ 955398.246] zxdg_output_v1#7.logical_size(2560, 1600)
[ 955398.249] wl_output#5.done()
[ 955398.251] wl_seat#8.name("seat0")
[ 955398.255] wl_seat#8.capabilities(3)
[ 955398.258] wl_shm#11.format(0)
[ 955398.262] wl_shm#11.format(1)
[ 955398.264] wl_shm#11.format(875709016)
[ 955398.266] wl_shm#11.format(875708993)
[ 955398.269] wl_shm#11.format(875710274)
[ 955398.272] wl_shm#11.format(842094674)
[ 955398.274] wl_shm#11.format(842088786)
[ 955398.277] wl_shm#11.format(892426322)
[ 955398.280] wl_shm#11.format(892420434)
[ 955398.282] wl_shm#11.format(909199186)
[ 955398.284] wl_shm#11.format(808665688)
[ 955398.287] wl_shm#11.format(808665665)
[ 955398.289] wl_shm#11.format(1211384408)
[ 955398.291] wl_shm#11.format(1211384385)
[ 955398.295] wl_shm#11.format(942948952)
[ 955398.297] wl_shm#11.format(942948929)
[ 955398.299] wl_callback#19.done(150854)
[ 955398.329] -> wl_seat#8.get_keyboard(new id wl_keyboard#19)
[ 955399.943] -> zwp_text_input_manager_v3#16.get_text_input(new id zwp_text_input_v3#20, wl_seat#8)
[ 955399.953] -> wl_compositor#3.create_surface(new id wl_surface#21)
[ 955399.961] -> wp_viewporter#10.get_viewport(new id wp_viewport#22, wl_surface#21)
[ 955399.969] -> wl_seat#8.get_pointer(new id wl_pointer#23)
[ 955399.976] -> wl_registry#2.bind(41, "wp_cursor_shape_manager_v1", 1, new id [unknown]#24)
[ 955399.984] -> wp_cursor_shape_manager_v1#24.get_pointer(new id wp_cursor_shape_device_v1#25, wl_pointer#23)
[ 955399.994] -> zwp_relative_pointer_manager_v1#17.get_relative_pointer(new id zwp_relative_pointer_v1#26, wl_pointer#23)
[ 955416.142] {Default Queue} -> wl_display#1.get_registry(new id wl_registry#2)
[ 955416.184] {Default Queue} wl_registry#2.global(1, "wl_shm", 2)
[ 955416.189] {Default Queue} wl_registry#2.global(2, "zwp_linux_dmabuf_v1", 4)
[ 955416.192] {Default Queue} -> wl_registry#2.bind(2, "zwp_linux_dmabuf_v1", 4, new id [unknown]#3)
[ 955416.195] {Default Queue} -> zwp_linux_dmabuf_v1#3.get_default_feedback(new id zwp_linux_dmabuf_feedback_v1#4)
[ 955416.197] {Default Queue} wl_registry#2.global(3, "wl_compositor", 6)
[ 955416.199] {Default Queue} wl_registry#2.global(4, "wl_subcompositor", 1)
[ 955416.201] {Default Queue} wl_registry#2.global(5, "wl_data_device_manager", 3)
[ 955416.206] {Default Queue} wl_registry#2.global(6, "zwlr_gamma_control_manager_v1", 1)
[ 955416.208] {Default Queue} wl_registry#2.global(7, "zxdg_output_manager_v1", 3)
[ 955416.210] {Default Queue} wl_registry#2.global(8, "ext_idle_notifier_v1", 1)
[ 955416.213] {Default Queue} wl_registry#2.global(9, "zwp_idle_inhibit_manager_v1", 1)
[ 955416.216] {Default Queue} wl_registry#2.global(10, "zwlr_layer_shell_v1", 4)
[ 955416.218] {Default Queue} wl_registry#2.global(11, "xdg_wm_base", 5)
[ 955416.221] {Default Queue} wl_registry#2.global(12, "zwp_tablet_manager_v2", 1)
[ 955416.223] {Default Queue} wl_registry#2.global(13, "org_kde_kwin_server_decoration_manager", 1)
[ 955416.225] {Default Queue} wl_registry#2.global(14, "zxdg_decoration_manager_v1", 1)
[ 955416.227] {Default Queue} wl_registry#2.global(15, "zwp_relative_pointer_manager_v1", 1)
[ 955416.229] {Default Queue} wl_registry#2.global(16, "zwp_pointer_constraints_v1", 1)
[ 955416.231] {Default Queue} wl_registry#2.global(17, "wp_presentation", 1)
[ 955416.233] {Default Queue} wl_registry#2.global(18, "wp_alpha_modifier_v1", 1)
[ 955416.235] {Default Queue} wl_registry#2.global(19, "zwlr_output_manager_v1", 4)
[ 955416.237] {Default Queue} wl_registry#2.global(20, "zwlr_output_power_manager_v1", 1)
[ 955416.239] {Default Queue} wl_registry#2.global(21, "zwp_input_method_manager_v2", 1)
[ 955416.242] {Default Queue} wl_registry#2.global(22, "zwp_text_input_manager_v3", 1)
[ 955416.244] {Default Queue} wl_registry#2.global(23, "ext_foreign_toplevel_list_v1", 1)
[ 955416.246] {Default Queue} wl_registry#2.global(24, "zwlr_foreign_toplevel_manager_v1", 3)
[ 955416.250] {Default Queue} wl_registry#2.global(25, "ext_session_lock_manager_v1", 1)
[ 955416.252] {Default Queue} wl_registry#2.global(26, "wp_drm_lease_device_v1", 1)
[ 955416.254] {Default Queue} wl_registry#2.global(27, "zwlr_export_dmabuf_manager_v1", 1)
[ 955416.257] {Default Queue} wl_registry#2.global(28, "zwlr_screencopy_manager_v1", 3)
[ 955416.259] {Default Queue} wl_registry#2.global(29, "zwlr_data_control_manager_v1", 2)
[ 955416.261] {Default Queue} wl_registry#2.global(30, "wp_security_context_manager_v1", 1)
[ 955416.264] {Default Queue} wl_registry#2.global(31, "wp_viewporter", 1)
[ 955416.266] {Default Queue} wl_registry#2.global(32, "wp_single_pixel_buffer_manager_v1", 1)
[ 955416.268] {Default Queue} wl_registry#2.global(33, "wp_content_type_manager_v1", 1)
[ 955416.272] {Default Queue} wl_registry#2.global(34, "wp_fractional_scale_manager_v1", 1)
[ 955416.274] {Default Queue} wl_registry#2.global(35, "wp_tearing_control_manager_v1", 1)
[ 955416.276] {Default Queue} wl_registry#2.global(36, "zxdg_exporter_v1", 1)
[ 955416.278] {Default Queue} wl_registry#2.global(37, "zxdg_importer_v1", 1)
[ 955416.280] {Default Queue} wl_registry#2.global(38, "zxdg_exporter_v2", 1)
[ 955416.281] {Default Queue} wl_registry#2.global(39, "zxdg_importer_v2", 1)
[ 955416.283] {Default Queue} wl_registry#2.global(40, "xdg_activation_v1", 1)
[ 955416.286] {Default Queue} wl_registry#2.global(41, "wp_cursor_shape_manager_v1", 1)
[ 955416.288] {Default Queue} wl_registry#2.global(42, "zwp_virtual_keyboard_manager_v1", 1)
[ 955416.290] {Default Queue} wl_registry#2.global(43, "zwlr_virtual_pointer_manager_v1", 2)
[ 955416.292] {Default Queue} wl_registry#2.global(44, "zwp_keyboard_shortcuts_inhibit_manager_v1", 1)
[ 955416.294] {Default Queue} wl_registry#2.global(45, "zwp_pointer_gestures_v1", 3)
[ 955416.296] {Default Queue} wl_registry#2.global(46, "ext_transient_seat_manager_v1", 1)
[ 955416.299] {Default Queue} wl_registry#2.global(47, "wl_seat", 9)
[ 955416.301] {Default Queue} wl_registry#2.global(49, "zwp_primary_selection_device_manager_v1", 1)
[ 955416.303] {Default Queue} wl_registry#2.global(50, "wl_output", 4)
[ 955416.305] {Default Queue} -> wl_display#1.sync(new id wl_callback#5)
[ 955416.330] {Display Queue} wl_display#1.delete_id(5)
[ 955416.333] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.main_device(array[8])
[ 955416.423] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.format_table(fd 18, 4288)
[ 955416.428] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.tranche_target_device(array[8])
[ 955416.431] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.tranche_flags(0)
[ 955416.433] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.tranche_formats(array[536])
[ 955416.435] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.tranche_done()
[ 955416.437] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.done()
[ 955416.439] {Default Queue} wl_callback#5.done(150854)
[ 955416.441] {Default Queue} -> zwp_linux_dmabuf_feedback_v1#4.destroy()
[ 955416.443] {Default Queue} -> zwp_linux_dmabuf_v1#3.destroy()
[ 955492.511] {Default Queue} -> wl_display#1.get_registry(new id wl_registry#2)
[ 955492.547] {Default Queue} wl_registry#2.global(1, "wl_shm", 2)
[ 955492.551] {Default Queue} wl_registry#2.global(2, "zwp_linux_dmabuf_v1", 4)
[ 955492.555] {Default Queue} -> wl_registry#2.bind(2, "zwp_linux_dmabuf_v1", 4, new id [unknown]#3)
[ 955492.559] {Default Queue} -> zwp_linux_dmabuf_v1#3.get_default_feedback(new id zwp_linux_dmabuf_feedback_v1#4)
[ 955492.563] {Default Queue} wl_registry#2.global(3, "wl_compositor", 6)
[ 955492.566] {Default Queue} wl_registry#2.global(4, "wl_subcompositor", 1)
[ 955492.568] {Default Queue} wl_registry#2.global(5, "wl_data_device_manager", 3)
[ 955492.572] {Default Queue} wl_registry#2.global(6, "zwlr_gamma_control_manager_v1", 1)
[ 955492.574] {Default Queue} wl_registry#2.global(7, "zxdg_output_manager_v1", 3)
[ 955492.577] {Default Queue} wl_registry#2.global(8, "ext_idle_notifier_v1", 1)
[ 955492.580] {Default Queue} wl_registry#2.global(9, "zwp_idle_inhibit_manager_v1", 1)
[ 955492.582] {Default Queue} wl_registry#2.global(10, "zwlr_layer_shell_v1", 4)
[ 955492.585] {Default Queue} wl_registry#2.global(11, "xdg_wm_base", 5)
[ 955492.587] {Default Queue} wl_registry#2.global(12, "zwp_tablet_manager_v2", 1)
[ 955492.590] {Default Queue} wl_registry#2.global(13, "org_kde_kwin_server_decoration_manager", 1)
[ 955492.593] {Default Queue} wl_registry#2.global(14, "zxdg_decoration_manager_v1", 1)
[ 955492.595] {Default Queue} wl_registry#2.global(15, "zwp_relative_pointer_manager_v1", 1)
[ 955492.598] {Default Queue} wl_registry#2.global(16, "zwp_pointer_constraints_v1", 1)
[ 955492.601] {Default Queue} wl_registry#2.global(17, "wp_presentation", 1)
[ 955492.603] {Default Queue} wl_registry#2.global(18, "wp_alpha_modifier_v1", 1)
[ 955492.606] {Default Queue} wl_registry#2.global(19, "zwlr_output_manager_v1", 4)
[ 955492.609] {Default Queue} wl_registry#2.global(20, "zwlr_output_power_manager_v1", 1)
[ 955492.612] {Default Queue} wl_registry#2.global(21, "zwp_input_method_manager_v2", 1)
[ 955492.615] {Default Queue} wl_registry#2.global(22, "zwp_text_input_manager_v3", 1)
[ 955492.618] {Default Queue} wl_registry#2.global(23, "ext_foreign_toplevel_list_v1", 1)
[ 955492.620] {Default Queue} wl_registry#2.global(24, "zwlr_foreign_toplevel_manager_v1", 3)
[ 955492.623] {Default Queue} wl_registry#2.global(25, "ext_session_lock_manager_v1", 1)
[ 955492.625] {Default Queue} wl_registry#2.global(26, "wp_drm_lease_device_v1", 1)
[ 955492.628] {Default Queue} wl_registry#2.global(27, "zwlr_export_dmabuf_manager_v1", 1)
[ 955492.630] {Default Queue} wl_registry#2.global(28, "zwlr_screencopy_manager_v1", 3)
[ 955492.633] {Default Queue} wl_registry#2.global(29, "zwlr_data_control_manager_v1", 2)
[ 955492.635] {Default Queue} wl_registry#2.global(30, "wp_security_context_manager_v1", 1)
[ 955492.638] {Default Queue} wl_registry#2.global(31, "wp_viewporter", 1)
[ 955492.640] {Default Queue} wl_registry#2.global(32, "wp_single_pixel_buffer_manager_v1", 1)
[ 955492.643] {Default Queue} wl_registry#2.global(33, "wp_content_type_manager_v1", 1)
[ 955492.645] {Default Queue} wl_registry#2.global(34, "wp_fractional_scale_manager_v1", 1)
[ 955492.648] {Default Queue} wl_registry#2.global(35, "wp_tearing_control_manager_v1", 1)
[ 955492.650] {Default Queue} wl_registry#2.global(36, "zxdg_exporter_v1", 1)
[ 955492.653] {Default Queue} wl_registry#2.global(37, "zxdg_importer_v1", 1)
[ 955492.661] {Default Queue} wl_registry#2.global(38, "zxdg_exporter_v2", 1)
[ 955492.666] {Default Queue} wl_registry#2.global(39, "zxdg_importer_v2", 1)
[ 955492.668] {Default Queue} wl_registry#2.global(40, "xdg_activation_v1", 1)
[ 955492.671] {Default Queue} wl_registry#2.global(41, "wp_cursor_shape_manager_v1", 1)
[ 955492.673] {Default Queue} wl_registry#2.global(42, "zwp_virtual_keyboard_manager_v1", 1)
[ 955492.676] {Default Queue} wl_registry#2.global(43, "zwlr_virtual_pointer_manager_v1", 2)
[ 955492.678] {Default Queue} wl_registry#2.global(44, "zwp_keyboard_shortcuts_inhibit_manager_v1", 1)
[ 955492.681] {Default Queue} wl_registry#2.global(45, "zwp_pointer_gestures_v1", 3)
[ 955492.684] {Default Queue} wl_registry#2.global(46, "ext_transient_seat_manager_v1", 1)
[ 955492.686] {Default Queue} wl_registry#2.global(47, "wl_seat", 9)
[ 955492.689] {Default Queue} wl_registry#2.global(49, "zwp_primary_selection_device_manager_v1", 1)
[ 955492.691] {Default Queue} wl_registry#2.global(50, "wl_output", 4)
[ 955492.695] {Default Queue} -> wl_display#1.sync(new id wl_callback#5)
[ 955492.716] {Display Queue} wl_display#1.delete_id(5)
[ 955492.721] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.main_device(array[8])
[ 955492.809] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.format_table(fd 18, 4288)
[ 955492.812] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.tranche_target_device(array[8])
[ 955492.814] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.tranche_flags(0)
[ 955492.817] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.tranche_formats(array[536])
[ 955492.818] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.tranche_done()
[ 955492.821] {Default Queue} zwp_linux_dmabuf_feedback_v1#4.done()
[ 955492.823] {Default Queue} wl_callback#5.done(150856)
[ 955492.825] {Default Queue} -> zwp_linux_dmabuf_feedback_v1#4.destroy()
[ 955492.828] {Default Queue} -> zwp_linux_dmabuf_v1#3.destroy()
[2m2025-11-26T14:29:22.260189Z[0m [32m INFO[0m [2mbevy_render::renderer[0m[2m:[0m AdapterInfo { name: "Apple M2 (G14G B0)", vendor: 65541, device: 0, device_type: IntegratedGpu, driver: "Honeykrisp", driver_info: "Mesa 26.0.0-devel (git-ad2f112ac2)", backend: Vulkan }
[2m2025-11-26T14:29:22.539121Z[0m [32m INFO[0m [2mbevy_render::batching::gpu_preprocessing[0m[2m:[0m GPU preprocessing is fully supported on this device.
[ 955994.575] wl_keyboard#19.keymap(1, fd 50, 69462)
[ 955994.598] wl_keyboard#19.repeat_info(25, 600)
and then it just hangs there, no new output until it's killed
@tychedelia I saw that you mentioned elsewhere that you work with multi-window apps, so perhaps you have already encountered this and I'm just "holding it wrong", or perhaps you have an idea of what might be going wrong? (if not, sorry for the ping 🙈)
Instead, no window appears, but the app keeps running, presumably because the condition of "is there any window left open applies, meaning that the window was created enough for that, but not enough to be visible.
I could be wrong but I'm fairly sure bevy only check the "is there any window left open" condition when a window is closed. As for why the window isn't spawning it might be an issue with the way you're spawning it, could you share the code in spawn_scene?
@Freyja-moth thanks for taking a look :)
as for the code, it's literally the example in this repo, have a look at https://github.com/bevyengine/bevy/blob/main/examples/window/multiple_windows.rs, there's nothing else (other than the primary_window: None patch above)
I would be interested in whether you can reproduce this btw; could you test it please? (and what OS/window system you are using)
I have only tested wayland, I just now on x11 (through xwayland) and I can confirm the exact same behaviour on both.
Ran the example while removing the primary window. The window does take a fair bit longer to popup than using primary_window but otherwise completely normal, which should probably be looked at, I don't really see any reason for it to.
Try letting it run for a minute or two, see if it appears. Otherwise my best guess would be that it's a mac specific issue.
Currently running on arch linux with x11.
I just left it running almost an hour and nothing happened (with WAYLAND_DEBUG=1 to see if there is even an attempt at creating a window).
Otherwise my best guess would be that it's a mac specific issue.
If you mean macos, then no, I'm running on linux here :) If you mean the apple gpu driver in mesa, then sure maybe, but as far as I can tell bevy (or winit) is not even attempting to create anything.
I'll dust off an old intel computer tomorrow and run this on there to see if it behaves differently, but given what I've seen so far I would be very surprised.
Ended up doing it tonight, and I can confirm the exact same behaviour on an intel igpu and an nvidia dgpu (iris & nvk mesa drivers, respectively), so it's not related to the gpu.
I have also tested with weston to also rule out a sway bug, and again, same behaviour.
Huh! Just to maybe help unblock you, the appropriate thing here when there is no PrimaryWindow is to set ExitCondition::DontExit on the window plugin. But there's definitely weird timing issues with windows I've seen before so it's not entirely surprising to me that this is acting goofy.
I just tried adding exit_condition: bevy::window::ExitCondition::DontExit, in case it makes a difference, but it doesn't, the behaviour is identical (which is what I expected since the bug is not that the app closes, but that it keeps running without opening the window).
@tychedelia since you're also here, could you try running the multiple_windows bevy example with the patch above, and let us know what window system you're testing on?
I can't reproduce this on Linux/X11/XMonad, with the above patch exactly 1 window appears for me, after roughly 1 second delay.
The logic for spawning new windows is pretty simple: winit calls about_to_wait, bevy looks for Window components and tells winit to spawn them:
https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/state.rs#L459 https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/system.rs#L71
I don't see anywhere on bevy's side where an existing window can change that logic. This, and the fact that it behaves differently for different people, suggest to me that it's either a winit bug or us using winit wrong.
Hmm, I think the problem is that we check for new windows in https://docs.rs/winit/latest/winit/application/trait.ApplicationHandler.html#method.about_to_wait. If a window doesn't exist it kinda makes sense that it would be platform dependent if we ever get any events again from winit, and it also explains the weird variable length delay.
Ok, that is exactly what happens. As far as I can see the only way to fix this properly is to send a user event into the event loop when a window is added, as we can't depend on any of the other winit lifecycle methods to be called regularly enough. That would mean changing the message type in WinitPlugin<T>, as it's currently completely generic.