pub struct TrayHandle { /* private fields */ }Expand description
A cloneable, thread-safe handle used to update a running tray.
Every method sends a message to the event loop; if the loop has stopped they
return Error::Disconnected.
Implementations§
Source§impl TrayHandle
impl TrayHandle
Sourcepub fn set_icon(&self, icon: Icon) -> Result<()>
pub fn set_icon(&self, icon: Icon) -> Result<()>
Replaces the tray icon.
Examples found in repository?
examples/smoke.rs (line 67)
35fn main() {
36 // Hard stop so a hang shows up as a CI failure rather than a 6-hour job.
37 thread::spawn(|| {
38 thread::sleep(Duration::from_secs(20));
39 eprintln!("SMOKE_TIMEOUT: event loop did not finish");
40 std::process::exit(3);
41 });
42
43 let config = TrayConfig::new(demo_icon())
44 .tooltip("ldtray smoke")
45 .menu(demo_menu());
46
47 let tray = match Tray::new(config) {
48 Ok(tray) => tray,
49 Err(err) => {
50 // Expected on a headless box (e.g. Linux CI: no session bus). On a
51 // GUI OS the platform libraries always exist, so treat a failure
52 // there as a real regression.
53 if cfg!(any(target_os = "windows", target_os = "macos")) {
54 eprintln!("SMOKE_FAIL: Tray::new failed on a GUI OS: {err}");
55 std::process::exit(1);
56 }
57 eprintln!("SMOKE_SKIP: no tray in this environment: {err}");
58 return;
59 }
60 };
61
62 // Drive every mutating method from another thread, then stop the loop.
63 let handle = tray.handle();
64 let driver = thread::spawn(move || {
65 thread::sleep(Duration::from_millis(400));
66 let _ = handle.set_tooltip("updated tooltip");
67 let _ = handle.set_icon(demo_icon());
68 let _ = handle.set_menu(demo_menu());
69 let _ = handle.notify(Notification::new("ldtray", "smoke").with_icon(demo_icon()));
70 thread::sleep(Duration::from_millis(400));
71 let _ = handle.quit();
72 });
73
74 let mut events = 0usize;
75 let result = tray.run(|event: Event| {
76 events += 1;
77 println!("event: {event:?}");
78 });
79 let _ = driver.join();
80
81 match result {
82 Ok(()) => {
83 println!("SMOKE_OK: ran cleanly ({events} events)");
84 }
85 Err(err) => {
86 eprintln!("SMOKE_FAIL: event loop ended with error: {err}");
87 std::process::exit(2);
88 }
89 }
90}Sourcepub fn set_tooltip(&self, text: impl Into<String>) -> Result<()>
pub fn set_tooltip(&self, text: impl Into<String>) -> Result<()>
Replaces the hover tooltip text.
Examples found in repository?
examples/smoke.rs (line 66)
35fn main() {
36 // Hard stop so a hang shows up as a CI failure rather than a 6-hour job.
37 thread::spawn(|| {
38 thread::sleep(Duration::from_secs(20));
39 eprintln!("SMOKE_TIMEOUT: event loop did not finish");
40 std::process::exit(3);
41 });
42
43 let config = TrayConfig::new(demo_icon())
44 .tooltip("ldtray smoke")
45 .menu(demo_menu());
46
47 let tray = match Tray::new(config) {
48 Ok(tray) => tray,
49 Err(err) => {
50 // Expected on a headless box (e.g. Linux CI: no session bus). On a
51 // GUI OS the platform libraries always exist, so treat a failure
52 // there as a real regression.
53 if cfg!(any(target_os = "windows", target_os = "macos")) {
54 eprintln!("SMOKE_FAIL: Tray::new failed on a GUI OS: {err}");
55 std::process::exit(1);
56 }
57 eprintln!("SMOKE_SKIP: no tray in this environment: {err}");
58 return;
59 }
60 };
61
62 // Drive every mutating method from another thread, then stop the loop.
63 let handle = tray.handle();
64 let driver = thread::spawn(move || {
65 thread::sleep(Duration::from_millis(400));
66 let _ = handle.set_tooltip("updated tooltip");
67 let _ = handle.set_icon(demo_icon());
68 let _ = handle.set_menu(demo_menu());
69 let _ = handle.notify(Notification::new("ldtray", "smoke").with_icon(demo_icon()));
70 thread::sleep(Duration::from_millis(400));
71 let _ = handle.quit();
72 });
73
74 let mut events = 0usize;
75 let result = tray.run(|event: Event| {
76 events += 1;
77 println!("event: {event:?}");
78 });
79 let _ = driver.join();
80
81 match result {
82 Ok(()) => {
83 println!("SMOKE_OK: ran cleanly ({events} events)");
84 }
85 Err(err) => {
86 eprintln!("SMOKE_FAIL: event loop ended with error: {err}");
87 std::process::exit(2);
88 }
89 }
90}Replaces the context menu.
Examples found in repository?
examples/smoke.rs (line 68)
35fn main() {
36 // Hard stop so a hang shows up as a CI failure rather than a 6-hour job.
37 thread::spawn(|| {
38 thread::sleep(Duration::from_secs(20));
39 eprintln!("SMOKE_TIMEOUT: event loop did not finish");
40 std::process::exit(3);
41 });
42
43 let config = TrayConfig::new(demo_icon())
44 .tooltip("ldtray smoke")
45 .menu(demo_menu());
46
47 let tray = match Tray::new(config) {
48 Ok(tray) => tray,
49 Err(err) => {
50 // Expected on a headless box (e.g. Linux CI: no session bus). On a
51 // GUI OS the platform libraries always exist, so treat a failure
52 // there as a real regression.
53 if cfg!(any(target_os = "windows", target_os = "macos")) {
54 eprintln!("SMOKE_FAIL: Tray::new failed on a GUI OS: {err}");
55 std::process::exit(1);
56 }
57 eprintln!("SMOKE_SKIP: no tray in this environment: {err}");
58 return;
59 }
60 };
61
62 // Drive every mutating method from another thread, then stop the loop.
63 let handle = tray.handle();
64 let driver = thread::spawn(move || {
65 thread::sleep(Duration::from_millis(400));
66 let _ = handle.set_tooltip("updated tooltip");
67 let _ = handle.set_icon(demo_icon());
68 let _ = handle.set_menu(demo_menu());
69 let _ = handle.notify(Notification::new("ldtray", "smoke").with_icon(demo_icon()));
70 thread::sleep(Duration::from_millis(400));
71 let _ = handle.quit();
72 });
73
74 let mut events = 0usize;
75 let result = tray.run(|event: Event| {
76 events += 1;
77 println!("event: {event:?}");
78 });
79 let _ = driver.join();
80
81 match result {
82 Ok(()) => {
83 println!("SMOKE_OK: ran cleanly ({events} events)");
84 }
85 Err(err) => {
86 eprintln!("SMOKE_FAIL: event loop ended with error: {err}");
87 std::process::exit(2);
88 }
89 }
90}Removes the context menu.
Sourcepub fn notify(&self, notification: Notification) -> Result<()>
pub fn notify(&self, notification: Notification) -> Result<()>
Shows a desktop notification.
Examples found in repository?
examples/basic.rs (lines 50-54)
14fn main() {
15 // A 16x16 solid red icon.
16 let side = 16u32;
17 let mut rgba = Vec::with_capacity((side * side * 4) as usize);
18 for _ in 0..side * side {
19 rgba.extend_from_slice(&[220, 40, 40, 255]);
20 }
21 let icon = Icon::from_rgba(side, side, rgba).expect("valid icon");
22 let notify_icon = icon.clone();
23
24 let menu = Menu::new()
25 .item(MenuItem::button(SAY_HI, "Say hi"))
26 .item(MenuItem::checkbox(TOGGLE, "Toggle me", false))
27 .item(MenuItem::separator())
28 .item(MenuItem::button(QUIT, "Quit"));
29
30 let config = TrayConfig::new(icon).tooltip("ldtray example").menu(menu);
31
32 let tray = match Tray::new(config) {
33 Ok(tray) => tray,
34 Err(err) => {
35 eprintln!("tray unavailable: {err}");
36 eprintln!("(this is expected on a headless server — exiting cleanly)");
37 return;
38 }
39 };
40
41 let handle = tray.handle();
42 println!("tray is up — right-click it for the menu, or Ctrl-C to abort");
43
44 let result = tray.run(move |event| {
45 println!("event: {event:?}");
46 match event {
47 Event::Menu(id) if id.0 == SAY_HI => {
48 // Actions are shown on Linux; ignored (message still shown)
49 // elsewhere.
50 let _ = handle.notify(
51 Notification::new("ldtray", "Hello from the tray!")
52 .with_icon(notify_icon.clone())
53 .action(100, "Wave back"),
54 );
55 }
56 Event::NotificationAction(action) => {
57 println!("notification action clicked: {}", action.0);
58 }
59 Event::Menu(id) if id.0 == QUIT => {
60 let _ = handle.quit();
61 }
62 _ => {}
63 }
64 });
65
66 if let Err(err) = result {
67 eprintln!("event loop ended with error: {err}");
68 }
69}More examples
examples/smoke.rs (line 69)
35fn main() {
36 // Hard stop so a hang shows up as a CI failure rather than a 6-hour job.
37 thread::spawn(|| {
38 thread::sleep(Duration::from_secs(20));
39 eprintln!("SMOKE_TIMEOUT: event loop did not finish");
40 std::process::exit(3);
41 });
42
43 let config = TrayConfig::new(demo_icon())
44 .tooltip("ldtray smoke")
45 .menu(demo_menu());
46
47 let tray = match Tray::new(config) {
48 Ok(tray) => tray,
49 Err(err) => {
50 // Expected on a headless box (e.g. Linux CI: no session bus). On a
51 // GUI OS the platform libraries always exist, so treat a failure
52 // there as a real regression.
53 if cfg!(any(target_os = "windows", target_os = "macos")) {
54 eprintln!("SMOKE_FAIL: Tray::new failed on a GUI OS: {err}");
55 std::process::exit(1);
56 }
57 eprintln!("SMOKE_SKIP: no tray in this environment: {err}");
58 return;
59 }
60 };
61
62 // Drive every mutating method from another thread, then stop the loop.
63 let handle = tray.handle();
64 let driver = thread::spawn(move || {
65 thread::sleep(Duration::from_millis(400));
66 let _ = handle.set_tooltip("updated tooltip");
67 let _ = handle.set_icon(demo_icon());
68 let _ = handle.set_menu(demo_menu());
69 let _ = handle.notify(Notification::new("ldtray", "smoke").with_icon(demo_icon()));
70 thread::sleep(Duration::from_millis(400));
71 let _ = handle.quit();
72 });
73
74 let mut events = 0usize;
75 let result = tray.run(|event: Event| {
76 events += 1;
77 println!("event: {event:?}");
78 });
79 let _ = driver.join();
80
81 match result {
82 Ok(()) => {
83 println!("SMOKE_OK: ran cleanly ({events} events)");
84 }
85 Err(err) => {
86 eprintln!("SMOKE_FAIL: event loop ended with error: {err}");
87 std::process::exit(2);
88 }
89 }
90}Sourcepub fn quit(&self) -> Result<()>
pub fn quit(&self) -> Result<()>
Asks the event loop to stop. After this, Tray::run returns and the
tray icon is removed.
Examples found in repository?
examples/basic.rs (line 60)
14fn main() {
15 // A 16x16 solid red icon.
16 let side = 16u32;
17 let mut rgba = Vec::with_capacity((side * side * 4) as usize);
18 for _ in 0..side * side {
19 rgba.extend_from_slice(&[220, 40, 40, 255]);
20 }
21 let icon = Icon::from_rgba(side, side, rgba).expect("valid icon");
22 let notify_icon = icon.clone();
23
24 let menu = Menu::new()
25 .item(MenuItem::button(SAY_HI, "Say hi"))
26 .item(MenuItem::checkbox(TOGGLE, "Toggle me", false))
27 .item(MenuItem::separator())
28 .item(MenuItem::button(QUIT, "Quit"));
29
30 let config = TrayConfig::new(icon).tooltip("ldtray example").menu(menu);
31
32 let tray = match Tray::new(config) {
33 Ok(tray) => tray,
34 Err(err) => {
35 eprintln!("tray unavailable: {err}");
36 eprintln!("(this is expected on a headless server — exiting cleanly)");
37 return;
38 }
39 };
40
41 let handle = tray.handle();
42 println!("tray is up — right-click it for the menu, or Ctrl-C to abort");
43
44 let result = tray.run(move |event| {
45 println!("event: {event:?}");
46 match event {
47 Event::Menu(id) if id.0 == SAY_HI => {
48 // Actions are shown on Linux; ignored (message still shown)
49 // elsewhere.
50 let _ = handle.notify(
51 Notification::new("ldtray", "Hello from the tray!")
52 .with_icon(notify_icon.clone())
53 .action(100, "Wave back"),
54 );
55 }
56 Event::NotificationAction(action) => {
57 println!("notification action clicked: {}", action.0);
58 }
59 Event::Menu(id) if id.0 == QUIT => {
60 let _ = handle.quit();
61 }
62 _ => {}
63 }
64 });
65
66 if let Err(err) = result {
67 eprintln!("event loop ended with error: {err}");
68 }
69}More examples
examples/smoke.rs (line 71)
35fn main() {
36 // Hard stop so a hang shows up as a CI failure rather than a 6-hour job.
37 thread::spawn(|| {
38 thread::sleep(Duration::from_secs(20));
39 eprintln!("SMOKE_TIMEOUT: event loop did not finish");
40 std::process::exit(3);
41 });
42
43 let config = TrayConfig::new(demo_icon())
44 .tooltip("ldtray smoke")
45 .menu(demo_menu());
46
47 let tray = match Tray::new(config) {
48 Ok(tray) => tray,
49 Err(err) => {
50 // Expected on a headless box (e.g. Linux CI: no session bus). On a
51 // GUI OS the platform libraries always exist, so treat a failure
52 // there as a real regression.
53 if cfg!(any(target_os = "windows", target_os = "macos")) {
54 eprintln!("SMOKE_FAIL: Tray::new failed on a GUI OS: {err}");
55 std::process::exit(1);
56 }
57 eprintln!("SMOKE_SKIP: no tray in this environment: {err}");
58 return;
59 }
60 };
61
62 // Drive every mutating method from another thread, then stop the loop.
63 let handle = tray.handle();
64 let driver = thread::spawn(move || {
65 thread::sleep(Duration::from_millis(400));
66 let _ = handle.set_tooltip("updated tooltip");
67 let _ = handle.set_icon(demo_icon());
68 let _ = handle.set_menu(demo_menu());
69 let _ = handle.notify(Notification::new("ldtray", "smoke").with_icon(demo_icon()));
70 thread::sleep(Duration::from_millis(400));
71 let _ = handle.quit();
72 });
73
74 let mut events = 0usize;
75 let result = tray.run(|event: Event| {
76 events += 1;
77 println!("event: {event:?}");
78 });
79 let _ = driver.join();
80
81 match result {
82 Ok(()) => {
83 println!("SMOKE_OK: ran cleanly ({events} events)");
84 }
85 Err(err) => {
86 eprintln!("SMOKE_FAIL: event loop ended with error: {err}");
87 std::process::exit(2);
88 }
89 }
90}Trait Implementations§
Source§impl Clone for TrayHandle
impl Clone for TrayHandle
Source§fn clone(&self) -> TrayHandle
fn clone(&self) -> TrayHandle
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreAuto Trait Implementations§
impl Freeze for TrayHandle
impl RefUnwindSafe for TrayHandle
impl Send for TrayHandle
impl Sync for TrayHandle
impl Unpin for TrayHandle
impl UnsafeUnpin for TrayHandle
impl UnwindSafe for TrayHandle
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more