Closed radiohertz closed 10 months ago
There is internal API which we use for the LSP preview (EventLoopQuitBegiavior) https://docs.rs/i-slint-core/latest/i_slint_core/backend/trait.Backend.html#tymethod.run_event_loop
We should somehow expose a way to keep the event loop alive when there are no window.
I guess, in the mean time, you could try to re-run the event loop after it quits
Edit: since this comment, that API is gone and now it is the private API Backend::set_event_loop_quit_on_last_window_closed Which is used by the LSP preview https://github.com/slint-ui/slint/blob/f2281dd900fd0009b5ca8de33c75579116701c76/tools/lsp/preview.rs#L106
I had a small discussion with @tronical about that and the conclusion is that we need to add something.
Some ideas include:
slint::set_event_loop_quit_on_last_window_closed(bool)
that forward to the backend function and make the backend function public.slint::run_event_loop_with_config(...)
that allow to pass parameter such as whether the event loop should quit when the last window closes.One point is wether it is the responsability to the backend to terminate the eventloop when there are no more window, or if it is the responsability of the slint core library. (Currently it is the backend that do that, the slint library currently don't know much about windows)
I had a small discussion with @tronical about that and the conclusion is that we need to add something.
Some ideas include:
- A global
slint::set_event_loop_quit_on_last_window_closed(bool)
that forward to the backend function and make the backend function public.- A reference counted struct that keeps the application alive, like the QEventLoopLocker
- a new
slint::run_event_loop_with_config(...)
that allow to pass parameter such as whether the event loop should quit when the last window closes.One point is wether it is the responsability to the backend to terminate the eventloop when there are no more window, or if it is the responsability of the slint core library. (Currently it is the backend that do that, the slint library currently don't know much about windows)
I'm not familiar with backend, but I think option 1 looks good because it seems easy to use. That is useful and important.And i also want to konw if that's possible to add some function for window,such as hide()--not close the window,just make the window invisible to preserve the data within the current window elements and quickly display it when needed、is_showing()--return whether the window is showing or falsle、to_front()--When this function is called, the window will be pushed to the top of the desktop、request_focus()--When this function is called, the taskbar icon will flash to remind the user that an event has occurred or ended.Sorry, my suggestions seem a bit overwhelming, they are just my immature suggestions. You can refer to it at your discretion. Thank you for your work.
How about changing the hide behavior to really hide, but not close? This could be achieved by invoke system api, I guess.
I have the same use case, and went with something in the line of option 1 (using the hidden function and i_slint_backend_selector
). I also use the on_close_requested()
callback to drop the window and free resources.
A robust way of doing this would indeed be nice.
I need some help.
How can I keep the eventloop running when all windows are "hiden"? I don't quite understand the method discussed above. Do they mean that I need to change the source code?
Another, if a robust way will coming soon (as the issue is opened a year ago) ?
Thank you right here.
I've came up here looking for solution, but I see that this is not very active thread.
@Horbin-Magician The only solution is to re-run the eventloop when you need it. Other than that there is only a discussion of possible implementations.
For my tray app I guess I'll simply create a window and run()
it whenever I need to show the GUI.
@ogoffart Do you have any update regarding this?
I've came up here looking for solution, but I see that this is not very active thread.
@Horbin-Magician The only solution is to re-run the eventloop when you need it. Other than that there is only a discussion of possible implementations.
For my tray app I guess I'll simply create a window and
run()
it whenever I need to show the GUI.@ogoffart Do you have any update regarding this?
This is my solution. By using b.set_event_loop_quit_on_last_window_closed(false);
, the slint::ComponentHandle::hide
will not make slint::ComponentHandle::run
return.
use i_slint_backend_selector;
fn main() {
slint::platform::set_platform(Box::new(i_slint_backend_winit::Backend::new())).unwrap();
// some code
i_slint_backend_selector::with_platform(|b| {
b.set_event_loop_quit_on_last_window_closed(false);
b.run_event_loop()
}).unwrap();
}
As @Horbin-Magician , the workaround right now is to use private API:
Use the internal crate i-slint-backend-selector
In your Cargo.toml
[dependencies]
slint = "1.2.2"
i-slint-backend-selector = "=1.2.2"
Notice the =
sign in the version number as the internal private crate don't follow semver.
Then you can do
fn main() {
i_slint_backend_selector::with_platform(|b| {
b.set_event_loop_quit_on_last_window_closed(false);
}).unwrap();
//... your code here ...
}
fn main() { i_slint_backend_selector::with_platform(|b| { b.set_event_loop_quit_on_last_window_closed(false); }).unwrap(); //... your code here ... }
For me it doesn't seem to change the behaviour for some reason. I pushed a POC here I wanted some quake style reveal:
EDIT: Solved in https://github.com/melMass/poc/commit/3c0731ab32c514b6eabc45958c120befafa2c690 by forcing winit backend
If someone is trying to do a systray app, I made a basic demo using tray_ion
https://github.com/Guiguiprim/slint_systry_app
I tested it on Windows (the systray integration might need some more work on Linux)
Olivier and I discussed option 2 from https://github.com/slint-ui/slint/issues/1499#issuecomment-1578736553 once more and noticed that perhaps this could be implemented entirely in the run-time library without the backend needing to support it.
set_event_loop_quit..
function from Backend
traitslint::EventLoopLocker
increases on creation and decreases count on droplet _locker = slint::EventLoopLocker::new();
slint::run_event_loop();
We added slint::run_event_loop_until_quit()
function in rust, and added an argument to the C++ run_event_loop function.
Javascript is still missing (#4316)
Add a feature to keep the event loop running even if all windows are closed
Workaround using private API: https://github.com/slint-ui/slint/issues/1499#issuecomment-1794517946
Original issue
I was looking to create a system tray for my application and i couldn't because of this issue.
slint::ComponentHandle::hide
makesslint::ComponentHandle::run
return.Example: https://gist.github.com/qw0rd/b9e86a99129b31e502bd9e45d146a84e