-
Notifications
You must be signed in to change notification settings - Fork 66
Make systray::Application amenable to being shared across threads #13
Comments
@jonhoo If you've got any good ideas for this, let me know. I'm still not super familiar with Rust yet so I'm not sure if there's a idiom I may be missing. |
So, making it Another way to do it would be to have an |
I think I can do this by making the event receive channel member of the struct public. That way, we can just clone it and don't have to access the object itself while running .recv(), solving the event locking problem. It also gives users more choice in where to put that, in case they want to pool it with other channels or something. |
Why would it need to be public? Having access to an |
Ok, well, for now I can at least figure out a way to remove the dependency on &mut self/&self in wait_for_message (which I also need to rename to just something like run_message_loop heh) and we can continue from there, just to get a bit more functionality going. I've got a test case for changing an icon in another thread that I'm trying to make work, once I get something going for that I'll put it up here for review. I didn't plan on the channel being passed between threads, I was more thinking that if you already had a main thread that waits on other things, waiting on that event channel can be pooled with those things. Didn't realize select was unstable though. Hmm. |
Yeah, it is really unfortunate that select is unstable. See rust-lang/rust#27800. And it doesn't seem like there's been any progress on it lately. Forcing the user to handle events on another thread is annoying, I agree, but it might be the best you can do until select stabilizes :( |
Is it possible right now to update the icon while wait_for_message() is looping? |
In the mean time I'm using a custom pub fn try_wait_for_message(&mut self) -> bool {
match self.rx.try_recv() {
Ok(m) => {
if (*self.callback.borrow()).contains_key(&m.menu_index) {
let f = (*self.callback.borrow_mut()).remove(&m.menu_index).unwrap();
f(&self);
(*self.callback.borrow_mut()).insert(m.menu_index, f);
}
false
},
Err(e) => {
match e {
std::sync::mpsc::TryRecvError::Disconnected => {
if let Some(t) = self.windows_loop.take() {
t.join().ok();
}
true
},
std::sync::mpsc::TryRecvError::Empty => false,
}
},
}
} |
@bbigras That /should/ be a thing, right now it's just not because I didn't architect this well. Hoping to get back to finishing this up soon, with things like that in mind. |
I did trayicon API (trayicon-rs) with sender idea, so that you can plug your own sender (e.g. winit's EventLoop, or std::mpsc::channel::Sender) and the trayicon does not have main loop. It works great e.g. with winit because it inits main loop already. I didn't want my trayicon to have main loop. |
wait_for_message takes &mut self, which means we can't easily share the Application object between threads and also wait for menu selections. That makes systray less than useful for things like updating the icon without some sort of interaction (see #5 (comment)).
Figure out a nice way to deal with sharing a mutable Application object between multiple threads. Maybe returning an Arc+Mutex wrapped object in the first place and passing that to a static equivalent of "wait_for_message" or something?
The text was updated successfully, but these errors were encountered: