-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow eframe apps to be detached #3340
base: master
Are you sure you want to change the base?
Conversation
This looks very promising! Can you please add a working example too? 🙏 |
31caf84
to
2385348
Compare
Added a working example and fixed the CI issues (was on a Windows machine before, so I couldn't run the |
Btw, I went and changed one of my projects to this approach, and I noticed that although it does work, communication between the 'outer' code and the 'detached eframe app' is kinda clunky, since there's no way to access or modify the app data from the returned reference. The way I'm doing this at the moment is by leaking a struct SharedState {
flag: bool
}
struct MyApp {
shared: &'static RefCell<SharedState>
}
let shared_state = Box::leak(Box::new(RefCell::new(SharedState { flag: true }))) as &_;
let detached_app = eframe::run_detached_native(
...,
Box::new(|_cc| Box::new(MyApp { shared: shared_state }))
)
// 'shared_state' can be accessed and modified How would you feel about exposing a |
not sure I follow entirely but would this pr allow you to open a completely detached eframe, meaning you would have two separate event loops? |
What's the status of this PR? This would be very useful for Ruffle |
Is the problem that we need to give away ownership of the Btw, if there's anyway I can contribute, I would be happy to help. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a merging in of master
and testing with multi-viewports, otherwise its looking good
@@ -0,0 +1,7 @@ | |||
Example showing some UI controls like `Label`, `TextEdit`, `Slider`, `Button`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a good description
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the screenshot is not very useful either
); | ||
// Winit window managed by the application | ||
let winit_window = winit::window::WindowBuilder::new() | ||
.build(&event_loop) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Giving this a title of e.g. "winit window" would help explain to the user what is going on
ui.heading("My egui Application"); | ||
ui.horizontal(|ui| { | ||
let name_label = ui.label("Your name: "); | ||
ui.text_edit_singleline(&mut self.name) | ||
.labelled_by(name_label.id); | ||
}); | ||
ui.add(egui::Slider::new(&mut self.age, 0..=120).text("age")); | ||
if ui.button("Click each year").clicked() { | ||
self.age += 1; | ||
} | ||
ui.label(format!("Hello '{}', age {}", self.name, self.age)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of showing the generic egui application, it would be better to show some text about what is going on in this example
/// An eframe app detached from the event loop. | ||
/// | ||
/// This is useful to run `eframe` apps while still having control over the event loop. | ||
/// For example, when you need to have a window managed by `egui` and another managed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// For example, when you need to have a window managed by `egui` and another managed | |
/// For example, when you need to have a window managed by `eframe` and another managed |
/// Execute an app in a detached state. | ||
/// | ||
/// This allows you to control the event loop itself, which is necessary in a few | ||
/// occasions, like when you need a screen not managed by `egui`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// occasions, like when you need a screen not managed by `egui`. | |
/// occasions, like when you need a screen not managed by `eframe`. |
// Ignore window events for other windows | ||
if let Some(window) = self.winit_app.window() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to merge in master
and handle the case of multi-viewports
eframe
to run on an existing event loop #2875.One choice that I'm not really sure which I prefer is whether we should check for
window.id() == window_id
onWindowEvent
events inside theon_event
method or not. Since we're already exposing thewindow
, the user could easily check that outside. However, when writing some example code, it ended up looking really bad and confusing. At the same time, people who will use this are probably people who have a good understanding ofwinit
and GUI development in general, so maybe that's not an issue.This gist shows how the 2 approaches would look like:
https://gist.github.com/rockisch/c672345661dd5411f5611b7ab14faea0
This initial version of the PR has the check inside, but I could remove it if wanted.