added demo tray_icon. has a bug where clicks get "stuck" in the queue

This commit is contained in:
Nickiel12 2022-07-13 22:29:25 -07:00
parent cce730a57f
commit ed38b4aa73
6 changed files with 144 additions and 1 deletions

View file

@ -11,6 +11,9 @@ ctrlc = "3.2.1"
serde_json = "1.0" serde_json = "1.0"
crossbeam-channel = "0.5" crossbeam-channel = "0.5"
inputbot = {path = "D:\\Inputbot"} inputbot = {path = "D:\\Inputbot"}
winit = "0.25"
winapi = { version = "0.3.9", features = ["winuser", "windef", "minwindef", "shellapi", "libloaderapi", "commctrl", "basetsd"] }
trayicon = { version="0.1.3", features = ["crossbeam-channel"] }
[features] [features]
default = [] default = []

BIN
src/icon1.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
src/icon2.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View file

@ -6,6 +6,9 @@ use workctl::sync_flag;
use crate::modules::stream_states::state_update::StateUpdate; use crate::modules::stream_states::state_update::StateUpdate;
#[cfg(target_os = "windows")]
use modules::tray_icon;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
mod modules; mod modules;
@ -21,6 +24,10 @@ const SERVER_ADDRESS: &str = "10.0.0.209:5000";
const SERVER_ADDRESS: &str = "10.0.0.168:5000"; const SERVER_ADDRESS: &str = "10.0.0.168:5000";
fn main() { fn main() {
let icon = include_bytes!("icon1.ico");
let mut tray_icon = tray_icon::TrayIcon::setup(icon);
let settings_json = load_json(); let settings_json = load_json();
let hotkeys = Hotkeys::new(settings_json); let hotkeys = Hotkeys::new(settings_json);
@ -53,8 +60,11 @@ fn main() {
}, },
Err(_) => {}, Err(_) => {},
} }
let tick_update = state.tick(); let tick_update = state.tick();
handle_instructions(tick_update, &mut state, &socket, &hotkeys); handle_instructions(tick_update, &mut state, &socket, &hotkeys);
tray_icon.process_tray_messages();
} }
println!("closing main thread"); println!("closing main thread");
@ -109,4 +119,3 @@ fn update_all(state: &StreamState, socket: &Socket) {
socket.send(StateUpdate::Scene(state.current_scene).to_json().to_string()); socket.send(StateUpdate::Scene(state.current_scene).to_json().to_string());
socket.send(StateUpdate::PauseTimer(state.timer_paused_length.is_some()).to_json().to_string()); socket.send(StateUpdate::PauseTimer(state.timer_paused_length.is_some()).to_json().to_string());
} }

View file

@ -2,6 +2,7 @@
pub mod message_handler; pub mod message_handler;
pub mod socket_handler; pub mod socket_handler;
pub mod external_interface; pub mod external_interface;
pub mod tray_icon;
pub mod stream_states { pub mod stream_states {
pub mod stream_state; pub mod stream_state;

130
src/modules/tray_icon.rs Normal file
View file

@ -0,0 +1,130 @@
use core::mem::MaybeUninit;
use std::time::Duration;
use trayicon::*;
use winapi::um::winuser;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Events {
ClickTrayIcon,
DoubleClickTrayIcon,
Exit,
Item1,
Item2,
Item3,
Item4,
CheckItem1,
SubItem1,
SubItem2,
SubItem3,
}
pub struct TrayIcon {
tray_icon: trayicon::TrayIcon<Events>,
message_channel: crossbeam_channel::Receiver<Events>,
}
impl TrayIcon {
pub fn setup(icon: &[u8]) -> TrayIcon {
let (s, r) = crossbeam_channel::unbounded();
let icon1 = include_bytes!("./../icon1.ico");
let icon2 = include_bytes!("./../icon2.ico");
let second_icon = Icon::from_buffer(icon2, None, None).unwrap();
let first_icon = Icon::from_buffer(icon1, None, None).unwrap();
// Needlessly complicated tray icon with all the whistles and bells
let mut tray_icon = TrayIconBuilder::new()
.sender_crossbeam(s)
.icon_from_buffer(icon1)
.tooltip("Cool Tray 👀 Icon")
.on_click(Events::ClickTrayIcon)
.on_double_click(Events::DoubleClickTrayIcon)
.menu(
MenuBuilder::new()
.item("Item 3 Replace Menu 👍", Events::Item3)
.item("Item 2 Change Icon Green", Events::Item2)
.item("Item 1 Change Icon Red", Events::Item1)
.separator()
.checkable("This is checkable", true, Events::CheckItem1)
.submenu(
"Sub Menu",
MenuBuilder::new()
.item("Sub item 1", Events::SubItem1)
.item("Sub Item 2", Events::SubItem2)
.item("Sub Item 3", Events::SubItem3),
)
.with(MenuItem::Item {
name: "Item Disabled".into(),
disabled: true, // Disabled entry example
id: Events::Item4,
icon: None,
})
.separator()
.item("E&xit", Events::Exit),
)
.build()
.unwrap();
TrayIcon {
tray_icon,
message_channel: r,
}
}
pub fn process_tray_messages(&self) {
unsafe {
let mut msg = MaybeUninit::uninit();
let bret = winuser::PeekMessageW(msg.as_mut_ptr(), 0 as _, 0, 0, 1);
if bret > 0 {
winuser::TranslateMessage(msg.as_ptr());
winuser::DispatchMessageA(msg.as_ptr());
} else {
return;
}
}
let message = self.message_channel.recv_timeout(Duration::from_millis(10));
match message {
Err(_) => return,
Ok(message) => {
match message {
Events::DoubleClickTrayIcon => {
println!("Double click");
}
Events::ClickTrayIcon => {
println!("Single click");
}
Events::Exit => {
println!("Please exit");
todo!()
}
Events::Item1 => {
println!("item1");
//tray_icon.set_icon(&second_icon).unwrap();
}
Events::Item2 => {
println!("item2");
//tray_icon.set_icon(&first_icon).unwrap();
}
Events::Item3 => {
println!("item3");
/*tray_icon
.set_menu(
&MenuBuilder::new()
.item("New menu item", Events::Item1)
.item("Exit", Events::Exit),
)
.unwrap();*/
}
e => {
println!("{:?}", e);
}
}
}
}
}
}