Animation with request_repaint() does not work when deferred viewport is open
- Dominant language
- Rust
- Stars
- 30.6k
- Forks
- 2.1k
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 72
Description
**Describe the bug**
When multiple viewports are open, animations using request_repaint() work only on the active viewport, and requests to update other viewports are ignored.
**To Reproduce**
I have created a minimal demonstration, which is included below. Compile and run. See how animation works only on window that is clicked.
Replace show_viewport_deferred() on line 41 to show_viewport_immediate() to see expected behaviour.
**Expected behavior**
Animation to work identically in both windows.
**Demonstration**
```rust
use egui::{Color32, Painter, Shape, Ui, ViewportId};
fn main() -> eframe::Result {
let native_options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_position([0.0, 0.0])
.with_inner_size([500.0, 500.0]),
..Default::default()
};
return eframe::run_native(
"My egui App",
native_options,
Box::new(|_cc| Ok(Box::new(MyApp::default()))),
);
}
#[derive(Default)]
pub struct MyApp {
}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
paint_animation(ui);
second_viewport(ui);
request_updates(ui);
});
}
}
pub fn second_viewport(ui: &mut egui::Ui) -> ViewportId {
let title = "second viewport";
let id: ViewportId = ViewportId::from_hash_of(title);
ui.ctx().show_viewport_deferred(
id.clone(),
egui::ViewportBuilder::default()
.with_title(title)
.with_position([510.0, 0.0])
.with_inner_size([500.0, 500.0]),
move |ctx, _class| {
egui::CentralPanel::default().show(ctx, |ui| {
paint_animation(ui);
request_updates(ui);
});
},
);
id
}
pub fn paint_animation(ui: &mut Ui) {
let painter = Painter::new(
ui.ctx().clone(),
ui.layer_id(),
ui.available_rect_before_wrap(),
);
let step = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.subsec_millis()
/ 5;
painter.add(Shape::circle_filled(
[100.0 + step as f32, 100.0 + step as f32].into(),
100.0,
Color32::RED,
));
// Make sure we allocate what we used (everything)
ui.expand_to_include_rect(painter.clip_rect());
}
fn request_updates(ui: &mut Ui) {
let mut ids: Vec = Vec::new();
ui.ctx().input(|i| {
ids = i.raw.viewports.keys().cloned().collect();
});
for id in ids {
ui.ctx().request_repaint_of(id);
};
}
```
Contributor guide
Research direction
Start by running the supplied Rust reproduction and compare show_viewport_deferred() with show_viewport_immediate(). Trace request_repaint_of() for each ViewportId and how deferred viewports are handled. Done means animations update identically in both windows when repaint requests are sent to all viewports.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- desktop-dev, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100