import { Button, StandardButton, ProgressIndicator, VerticalBox } from \"std-widgets.slint\";\n\nexport component SettingsDialog inherits Dialog {\n\n title: \"Settings\";\n\n VerticalBox {\n spacing: 5px;\n ProgressIndicator {\n indeterminate: true;\n }\n\n Text {\n text: \"Multi-window trial\";\n }\n }\n\n StandardButton {\n kind: ok;\n }\n\n StandardButton {\n kind: cancel;\n }\n}\n\nexport component AppWindow inherits Window {\n height: 200px;\n width: 200px;\n\n callback show-settings();\n property <int> value: 100;\n timer := Timer {\n interval: 1s;\n running: true;\n triggered() => {\n value -= 1;\n if (value == 0) {\n self.running = false;\n }\n }\n }\n\n VerticalBox {\n spacing: 10px;\n Text {\n text: value;\n }\n\n ProgressIndicator {\n indeterminate: true;\n }\n\n Button {\n text: \"Show settings\";\n clicked => {\n root.show-settings()\n }\n }\n }\n}
For completeness I have tried this:
\nI thought this was an winit issue to begin with, but the RenderRequested events seem to come through no matter the focus using the winit only code below:
\nuse winit::event::{Event, WindowEvent};\nuse winit::event_loop::{ControlFlow, EventLoop};\nuse winit::window::WindowBuilder;\n\nfn main() {\n let event_loop = EventLoop::new();\n let window1 = WindowBuilder::new()\n .with_title(\"Window 1\")\n .build(&event_loop)\n .unwrap();\n let window2 = WindowBuilder::new()\n .with_title(\"Window 2\")\n .build(&event_loop)\n .unwrap();\n\n let mut counter1 = 0;\n let mut counter2 = 0;\n\n event_loop.run(move |event, _, control_flow| {\n *control_flow = ControlFlow::Poll;\n match event {\n Event::WindowEvent {\n event: WindowEvent::CloseRequested,\n ..\n } => {\n *control_flow = ControlFlow::Exit;\n }\n Event::MainEventsCleared => {\n counter1 += 1;\n counter2 += 1;\n window1.set_title(&format!(\"Window 1: {}\", counter1));\n window2.set_title(&format!(\"Window 2: {}\", counter2));\n window1.request_redraw();\n window2.request_redraw();\n }\n Event::RedrawRequested(id) => {\n // Add basic rendering logic here if needed\n println!(\"Redraw requested for window_{:?}\", id);\n }\n _ => {}\n }\n });\n}
Any help would be hugely appreciated as I have burnt way too many days trying work around this myself.
\nCheers, Chris.
","upvoteCount":1,"answerCount":2,"acceptedAnswer":{"@type":"Answer","text":"I think #8828 should fix this. Could you give it a try?
\nWith this PR, your example works, with one single change: It's important to avoid calling request_redraw()
directly on the winit::window::Window
and instead, in force_redraw_all_windows
replace the call to winit_window.request_redraw()
with window.window().request_redraw()
. Otherwise Slint's built-in throttle won't help.
-
Hey team, I've been using Slint for a while now and have developed a low-latency RTSP streaming application with it and GStreamer for remote operating machinery that is very nice to use. I am trying to add two remote windows for additional streams. When I try to run the app on Windows 11 (works fine on mac) it only wants to render the window content of the in-focus window. I've reduced this to a very basic example using slint, and winit to force redraw requests, but the problem still persists. Code below: use slint::{winit_030::WinitWindowAccessor, ComponentHandle, PlatformError, Timer, Weak};
use std::time::Duration;
slint::include_modules!();
fn main() -> Result<(), slint::PlatformError> {
slint::BackendSelector::new()
.backend_name("winit".into())
.select()?;
let window_1 = AppWindow::new()?;
let window_2 = AppWindow::new()?;
window_1
.window()
.set_rendering_notifier(|e, g| println!("rendering window 1: {:?}", e))
.unwrap();
window_2
.window()
.set_rendering_notifier(|e, g| println!("rendering window 2: {:?}", e))
.unwrap();
window_1.on_show_settings(|| {
let dialog = SettingsDialog::new().unwrap();
dialog.show().unwrap();
});
window_1.show()?;
window_2.show()?;
let windows = vec![window_1.as_weak(), window_2.as_weak()];
let timer = Timer::default();
let mut counter1 = 0;
timer.start(
slint::TimerMode::Repeated,
Duration::from_millis(16),
move || {
force_redraw_all_windows(&windows, &mut counter1).unwrap();
},
);
slint::run_event_loop()?;
Ok(())
}
fn force_redraw_all_windows(
windows: &[Weak<AppWindow>],
counter: &mut i32,
) -> Result<(), PlatformError> {
for weak_window in windows {
if let Some(window) = weak_window.upgrade() {
window
.window()
.with_winit_window(|winit_window: &winit::window::Window| {
winit_window.request_redraw();
*counter += 1;
winit_window.set_title(&format!("{}", counter));
eprintln!("window id = {:#?}", winit_window.id());
eprintln!("Counter value: {}", counter);
});
}
}
Ok(())
} import { Button, StandardButton, ProgressIndicator, VerticalBox } from "std-widgets.slint";
export component SettingsDialog inherits Dialog {
title: "Settings";
VerticalBox {
spacing: 5px;
ProgressIndicator {
indeterminate: true;
}
Text {
text: "Multi-window trial";
}
}
StandardButton {
kind: ok;
}
StandardButton {
kind: cancel;
}
}
export component AppWindow inherits Window {
height: 200px;
width: 200px;
callback show-settings();
property <int> value: 100;
timer := Timer {
interval: 1s;
running: true;
triggered() => {
value -= 1;
if (value == 0) {
self.running = false;
}
}
}
VerticalBox {
spacing: 10px;
Text {
text: value;
}
ProgressIndicator {
indeterminate: true;
}
Button {
text: "Show settings";
clicked => {
root.show-settings()
}
}
}
} For completeness I have tried this:
I thought this was an winit issue to begin with, but the RenderRequested events seem to come through no matter the focus using the winit only code below: use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::WindowBuilder;
fn main() {
let event_loop = EventLoop::new();
let window1 = WindowBuilder::new()
.with_title("Window 1")
.build(&event_loop)
.unwrap();
let window2 = WindowBuilder::new()
.with_title("Window 2")
.build(&event_loop)
.unwrap();
let mut counter1 = 0;
let mut counter2 = 0;
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::MainEventsCleared => {
counter1 += 1;
counter2 += 1;
window1.set_title(&format!("Window 1: {}", counter1));
window2.set_title(&format!("Window 2: {}", counter2));
window1.request_redraw();
window2.request_redraw();
}
Event::RedrawRequested(id) => {
// Add basic rendering logic here if needed
println!("Redraw requested for window_{:?}", id);
}
_ => {}
}
});
} Any help would be hugely appreciated as I have burnt way too many days trying work around this myself. Cheers, Chris. |
Beta Was this translation helpful? Give feedback.
-
Hi Chris. I tried your example and I can reproduce the issue on Windows. It's... rather strange indeed. I can confirm that we do invoke the renderer on the other windows. Even with the software renderer (and soft buffer), the window decorations update with the new title but the contents don't. |
Beta Was this translation helpful? Give feedback.
-
I gave your PR a spin this morning, and while it is closer to the goal, the issue is still present. I added a 3rd window to the mix to show off the differences in rendering, depending on which window is selected. Screen.Recording.2025-07-02.051558.mp4Screen.Recording.2025-07-02.051755.mp4Screen.Recording.2025-07-02.053139.mp4 |
Beta Was this translation helpful? Give feedback.
I think #8828 should fix this. Could you give it a try?
With this PR, your example works, with one single change: It's important to avoid calling
request_redraw()
directly on thewinit::window::Window
and instead, inforce_redraw_all_windows
replace the call towinit_window.request_redraw()
withwindow.window().request_redraw()
. Otherwise Slint's built-in throttle won't help.