Egui/eframe winit application that can open multiple windows

I'm trying to keep the display connection open and have my program idle in the background so future windows can be opened with minimal latency.

the problem I have is thus: eframe bundles together winit::EventLoop and winit::Window into a singular abstraction that is created and destroyed as a unit, however any alternative interface that doesn't bundle these to together also makes a bunch of different distinctions I don't care about.

I don't care about hardware acceleration, I don't care about fancy event preprocessing, I basically just want a function that will take a winit::Window and give me an egui::Ui.

Is there a crate that is capable of operating at this level of abstraction, or at least an example that shows how to use egui_winit without a ton of boilerplate?

egui now supports multiple native windows, it's called "viewports", see the documentation for the concepts and usage:

other alternative to eframe is to write you own integration crate for egui, winit, and a painter backend.

The root viewport is the original viewport, and cannot be closed without closing the application.

so that doesn't work.

other alternative to eframe is to write you own integration crate for egui, winit, and a painter backend.

I was hoping someone had already done that...

too bad it doesn't fit your use case.

but depending on your use case, there may be a workaround: although you cannot close the root viewport, you can "hide" it (unfortunately, it does NOT work for all platforms, see platform specific behavior of Window::set_visible()).

here's an example, which you can test out on platforms that do support "hiding" windows such as X11. just add this snippet to the update() method of the viewport example program:

if ui.button("hide window").clicked() {
	// hide "current" window
	//let viewport = ctx.viewport_id();
	// hide "root" window
	let viewport = ViewportId::ROOT;
	ctx.send_viewport_cmd_to(viewport, egui::ViewportCommand::Visible(false));
	// in this example, I just use a thread to re-"open" the window after 5 seconds
	let ctx = ctx.clone();
	std::thread::spawn(move || {
		std::thread::sleep(Duration::from_secs(5));
		ctx.send_viewport_cmd_to(viewport, egui::ViewportCommand::Visible(true));
		ctx.request_repaint();
	});
}

yeah i already tried "hiding" windows, doesn't work on wayland.

Bevy with bevy_egui can do this. It is also the only framework i found that can do this in wasm. You just have to set the ExitCondition to DontExit

While you can remove most of bevys plugins this is probably still too heavy. (or maybe not). As bevy wants to control the event loop

From the implementation side it is quite easy though, you can just spawn a window and it will have an EguiContext

1 Like

actually, I had something working for my own use, but it was for (very) old version of egui and winit, it won't work for later versions.

when egui introduced the viewport API, although it is very different from my hacky approach, it has the features I need, so I abandoned my sloppy implementation.

if you are interested, I'm happy to upload it to github. just keep in mind, it is VERY old and NOT compatible with current version of the crates.

we all know, among desktop platforms, wayland is always the special one.

I wanted my toolbar shaped window to be opened at certain location on the desktop, but wayland says, nope, only I, the compositor, am allowed to position your window.

idk why wayland needs to have things never exist rather than just allowing compositors the discretion to ignore them based on user preference.

expecially when xwayland exists, which is what i ended up just using.