Giter VIP home page Giter VIP logo

tray-item-rs's Introduction

Multi-platform Tray Indicator

Cargo Check CircleCI

Please see the examples as documentation is currently lacking.

Tray Indicator uses icons from gresources on Linux and .rc-files on Windows.
These resourses have to be packed into the final binary.

  • Linux
  • Windows
  • MacOS*

* MacOS does not allow running applications in threads other than main, meaning that it is not possible to listen for events in a new thread. See the macos.rs example for a how-to.

Todo:

  • Docs

tray-item-rs's People

Contributors

absolucy avatar amionsky avatar benfaerber avatar bowarc avatar canadahonk avatar dasprid avatar dkrisman avatar felixmaker avatar fgimian avatar icemic avatar iwittenberg avatar njust avatar not-holar avatar oko avatar olback avatar sharunkumar avatar stephengeorgewest avatar windoze avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

tray-item-rs's Issues

Failes to build on linux

   Compiling tray-item v0.8.0 (/home/dilawars/Work/FORKES/tray-item-rs)
error[E0433]: failed to resolve: could not find `TrayItemImpl` in `api`
  --> src/lib.rs:30:22
   |
30 |         Ok(Self(api::TrayItemImpl::new(title, icon)?))
   |                      ^^^^^^^^^^^^ could not find `TrayItemImpl` in `api`

error[E0412]: cannot find type `TrayItemImpl` in module `api`
 --> src/lib.rs:5:26
  |
5 | pub struct TrayItem(api::TrayItemImpl);
  |                          ^^^^^^^^^^^^ not found in `api`

error[E0412]: cannot find type `TrayItemImpl` in module `api`
  --> src/lib.rs:48:46
   |
48 |     pub fn inner_mut(&mut self) -> &mut api::TrayItemImpl {
   |                                              ^^^^^^^^^^^^ not found in `api`

Some errors have detailed explanations: E0412, E0433.
For more information about an error, try `rustc --explain E0412`.
error: could not compile `tray-item` due to 3 previous errors

Mac example with custom icons

This super simple example does work on my mac:

use tray_item::{IconSource, TrayItem};

fn main() {
    let mut tray = TrayItem::new("Tray Example", IconSource::Resource("")).unwrap();

    let mut inner = tray.inner_mut();
    inner.display();
}

But I want to see an example where I can display a custom png icon and then based on some event or condition - change that icon to something else. It's not clear how to do this in this case.

MacOS: Unable to load icon

    pub fn set_icon(&mut self, icon: &str) -> Result<(), TIError> {
        unsafe {
            let icon_name = NSString::alloc(nil).init_str(icon);
            self.icon = Some(NSImage::initWithContentsOfFile_(
                NSImage::alloc(nil),
                icon_name,
            ));
        }
        Ok(())
    }

I try to modify set_icon and use full path instead because I didn't know how imageNamed_ consume icon there.
Anyway I didn't have much luck, even program didn't start properly when i changed.

Any hint is welcome.

System Tray Disappears On Windows When Explorer Crashes/Restarts

When explorer.exe crashes or restarts the icon disappears from the system tray.

Steps to reproduce:

  • Run the windows example
  • Open Task Manager to the Processes tab and find "Windows Explorer" and right click and then select "restart"

After a few seconds the taskbar will reload and when you navigate to the system tray area the icon will be gone but the application will still be running(you can see the process exe is still running if you look at Task Manager). No output is shown on the terminal you run the example from.

This seems to be due to windows wiping everything in the system tray when it crashes/restarts. I did some digging and it looks like windows provides a way to "listen" for when the system tray gets recreated so a app can readd itself. I just don't know enough to implement this and send a PR.

This link provides some info on what happens https://docs.microsoft.com/en-us/windows/win32/shell/taskbar?redirectedfrom=MSDN#taskbar-creation-notification

With Microsoft Internet Explorer 4.0 and later, the Shell notifies applications that the taskbar has been created. When the taskbar is created, it registers a message with the TaskbarCreated string and then broadcasts this message to all top-level windows. When your taskbar application receives this message, it should assume that any taskbar icons it added have been removed and add them again. This feature generally applies only to services that are already running when the Shell launches. The following example shows a very simplified method for handling this case.

On Windows 10, the taskbar also broadcasts this message when the DPI of the primary display changes.

cannot run example windows

Man I like the language, but around 90% of the examples I run from repos just fail or don't even build.

cargo run --example macos                                                                              
   Compiling tray-item v0.9.0 (C:\Users\...\Projects\Rust\tray-item-rs)
error[E0599]: no method named `add_quit_item` found for mutable reference `&mut tray_item::api::windows::TrayItemWindows` in the current scope
  --> examples\macos.rs:14:11
   |
14 |     inner.add_quit_item("Quit");
   |           ^^^^^^^^^^^^^ help: there is a method with a similar name: `add_menu_item`

error[E0599]: no method named `display` found for mutable reference `&mut tray_item::api::windows::TrayItemWindows` in the current scope
  --> examples\macos.rs:15:11
   |
15 |     inner.display();
   |           ^^^^^^^ method not found in `&mut TrayItemWindows`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `tray-item` (example "macos") due to 2 previous errors

Icon support

First off: thanks for putting effort into tackling this problem and sharing your solution. So, systray-rs was deprecated, because the developer didn't have time to catch up with all the rust changes. He basically warned others who wanted to make a successor to this to tackle the problem from a cross-platform perspective, which seems to be pretty hard to tackle. There's also trayicon-rs, but that does not have any cross-platform support at the time. So I'm really glad that you've actually created a very usable library for this exact purpose!

So onto the actual issue... I was wondering if you have any plans or ideas on icon support. How would that realistically function, cross-platform?

Some considerations:

  • On MacOS, tray icons are stencil-like, monochrome items. On Windows, tray icons are generally more detailed images. Supporting multiple (.png?) images would solve this

Linux: unable to load icon via GResource

Hi,

I saw in your comment here that icons on linux can be loaded via gresources.
I tried but unfortunately it shows only a black box:
image

I tried to load the icon resource via gio::resources_lookup_data, which is successful. So it seems the resource itself is correctly packed and loaded.

use tray_item::TrayItem;
use gtk;
use gio::ResourceLookupFlags;

fn main() {
    gtk::init().unwrap();

    let res_bytes = include_bytes!("../resources.gresource");
    let data = glib::Bytes::from(&res_bytes[..]);
    let resources = gio::Resource::from_data(&data).unwrap();
    gio::resources_register(&resources);

    // let svg = gio::resources_lookup_data("/org/gtk/test/assets/test.svg", ResourceLookupFlags::all()).expect("Failed to load svg");
    // println!("Svg size: {}", svg.len());
    let png = gio::resources_lookup_data("/org/gtk/test/assets/test.png", ResourceLookupFlags::all()).expect("Failed to load png");
    println!("Png size: {}", png.len());

    let mut tray = TrayItem::new("Tray Example", "/org/gtk/test/assets/test.png").unwrap();
    tray.set_icon("/org/gtk/test/assets/test.png");
    // let mut tray = TrayItem::new("Tray Example", "/org/gtk/test/assets/test.png").unwrap();
    // let mut tray = TrayItem::new("Tray Example", "accessories-calculator").unwrap();

    tray.add_label("Tray Label").unwrap();

    tray.add_menu_item("Hello", || {
        println!("Hello!");
    }).unwrap();

    tray.add_menu_item("Quit", || {
        gtk::main_quit();
    }).unwrap();

    gtk::main();

}

Any idea what's missing? Full example is here:
https://github.com/njust/tray_test.

Update tray name/title

Thanks @olback for this crate!

I'm wondering if you think it's possible to update the tray name after it is created. I can try implementing it for macos and linux if you think this is a good addition to this crate

Switching to windows-rs and resolving various issues

Hey there, I thought I'd open an issue before sending a PR to ensure this is something you're interested in.

This evening, I went through a major refactor of the Windows implementation, switched to windows-rs (specifically the lighter weight windows-sys crate) which now supports cross-compilation and resolved the unicode tooltip issue reported at #27

You may check out my branch at https://github.com/fgimian/tray-item-rs/tree/switch-to-windows-rs

Please let me know if this is something you would be interested in and I'll drop you a PR 😄

Cheers
Fotis

add_label -> update_label

Had an idea of making like a stock ticker tray icon. Obvious price is rapidly changing. Was wondering if we could make a set_label API or update_label API to update it to a new value after initialization

windows ico load can't

I used windres.

... tray-item-0.6.0\src\api\windows\funcs.rs", line: 36

let mut tray = tray_item::TrayItem::new("rust-tray", "windres-tray.ico").unwrap();

... -_- g,.g

cargo build becomes
But,
cargo run does not work.

The icon of the exe file entered fine.

Thanks.

Debian 11 : gtk_widget_get_scale_factor: assertion 'GTK_IS_WIDGET (widget)' failed

Linux example fail with Debian 11 (Gnome) :

bux@pc59:~$ git clone https://github.com/olback/tray-item-rs.git
Clonage dans 'tray-item-rs'...
remote: Enumerating objects: 183, done.
remote: Counting objects: 100% (28/28), done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 183 (delta 16), reused 14 (delta 12), pack-reused 155
Réception d'objets: 100% (183/183), 74.60 Kio | 821.00 Kio/s, fait.
Résolution des deltas: 100% (69/69), fait.
bux@pc59:~$ cd tray-item-rs/
bux@pc59:~/tray-item-rs$ cargo run --example linux
    Updating crates.io index
  Downloaded libc v0.2.132
  [...]
   Compiling libappindicator v0.7.1
   Compiling tray-item v0.7.0 (/home/bux/tray-item-rs)
    Finished dev [unoptimized + debuginfo] target(s) in 2m 40s
     Running `target/debug/examples/linux`

(linux:34675): Gtk-CRITICAL **: 20:13:00.240: gtk_widget_get_scale_factor: assertion 'GTK_IS_WIDGET (widget)' failed

I can make some investigation if needed !

Critical error: gdk_window_thaw_toplevel_updates: ...

I'm using the example for linux, but keep getting this error:

(ocean-drive:69679): Gdk-CRITICAL **: 00:09:26.145: gdk_window_thaw_toplevel_updates: assertion 'window->update_and_descendants_freeze_count > 0' failed

The app is working after printing this error and I can press buttons and get Hello! in the console, but this error is kinda annoying (because I want my program to have clean output without errors from third-party sources) and I don't know how to get rid of it.

How can I fix it and whats the cause of this?

The actual code:

// Basically, it's just copy-pasted code from the examples
use tray_item::TrayItem;
use gtk;

// ...
gtk::init().unwrap();
// trayicon.png is an custom icon in the project root
// if you want to know, I get the same error with default GTK icons
let mut tray = TrayItem::new("Tray Example", "./trayicon.png").unwrap();

tray.add_label("Tray Label").unwrap();

tray.add_menu_item("Hello", || {
  println!("Hello!");
}).unwrap();

tray.add_menu_item("Quit", || {
  gtk::main_quit();
}).unwrap();

gtk::main();

Cargo.toml:

tray-item = "0.6.0"
gtk = "0.14.0"

Make possible to trigger an action by clicking over icon

Currently as I see the only way to trigger some action is to create a menu option. After that open the menu by clicking on the icon and choosing the needed option.
I didn't find a way how to trigger some action just by clicking once over the icon.

Question about Mac

Will using an async executor and channels bypass the Mac single threaded limitation?

Include Icon in Executable

Hi!

Is it possible to create the icon from bytes? I'd like to use include_bytes! in order to avoid having to create an installer that puts an .ico file somewhere.

The system cannot find the path specified when running the windows example.

I cannot seem to compile the windows example standalone.

I cd to tray-item-rs\examples\windows and run cargo check, I get faced with a The system cannot find the path specified in the build.rs

env::current_dir() does print \tray-item-rs\examples\windows.

Trying to just open the file in the build script via let file = std::fs::File::open("tray-example.rs").unwrap() also panics the same.

Interestingly, using glob's glob::glob("*.rc") and using that path buffer in the File::open() suddenly makes it magically find it. It does not, however, work in the Build::new().compile().

I am on W11, latest stable and nightly both produce the error.

Error when trying to start tray-item from a spawned thread in linux

I'm trying to combine tray-item and druid so that I can show a window from a tray-item event (e.g. clicking a menu entry).

I'm using druid to create a window (which will be initially hidden), and give trayitem the handler to send commands to so the window can react to menu events from system tray.

My code is as follows:

pub fn create_window() -> Result<(), PlatformError> {
    let main_window = WindowDesc::new(build_root_widget)
        .title("Some window")
        .window_size((400.0, 400.0));

    let initial_state: HelloState = HelloState { name: "World".into() };

    let launcher = AppLauncher::with_window(main_window);
    let event_sink = launcher.get_external_handle();
    thread::spawn(move || create_tray_icon(event_sink));
    // ...
}

fn create_tray_icon(event_sink: ExtEventSink) {
    gtk::init().unwrap();
    let mut tray = TrayItem::new("Some Example", "accessories-calculator").unwrap();
    // ... other code as per linux.rs example.
}

// ... other functions to build the UI, etc.

So I'm using thread::spawn to create the tray item.

However, I'm getting the following error when the gtk::init() is run:

Gdk-ERROR **: 12:57:41.458: The program 'jack-testing' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadImplementation (server does not implement operation)'.
  (Details: serial 162 error_code 17 request_code 20 (core protocol) minor_code 0)
  (Note to programmers: normally, X errors are reported asynchronously;
   that is, you will receive the error a while after causing it.
   To debug your program, run it with the GDK_SYNCHRONIZE environment
   variable to change this behavior. You can then get a meaningful
   backtrace from your debugger if you break on the gdk_x_error() function.)

Is it possible to create the tray in a separate thread in linux?

Cheers,
Mark

Fails to build on linux

   Compiling tray-item v0.8.0 (/home/dilawars/Work/FORKES/tray-item-rs)
error[E0433]: failed to resolve: could not find `TrayItemImpl` in `api`
  --> src/lib.rs:30:22
   |
30 |         Ok(Self(api::TrayItemImpl::new(title, icon)?))
   |                      ^^^^^^^^^^^^ could not find `TrayItemImpl` in `api`

error[E0412]: cannot find type `TrayItemImpl` in module `api`
 --> src/lib.rs:5:26
  |
5 | pub struct TrayItem(api::TrayItemImpl);
  |                          ^^^^^^^^^^^^ not found in `api`

error[E0412]: cannot find type `TrayItemImpl` in module `api`
  --> src/lib.rs:48:46
   |
48 |     pub fn inner_mut(&mut self) -> &mut api::TrayItemImpl {
   |                                              ^^^^^^^^^^^^ not found in `api`

Some errors have detailed explanations: E0412, E0433.
For more information about an error, try `rustc --explain E0412`.
error: could not compile `tray-item` due to 3 previous errors

when build for windows x86, got errors

cargo build --release --target=i686-pc-windows-msvc
error[E0793]: reference to packed field is unaligned
   --> D:\Applications\Scoop\persist\rustup\.cargo\registry\src\index.crates.io-6f17d22bba15001f\tray-item-0.8.0\src\api\windows\mod.rs:201:9
    |
201 |         nid.szTip[..wide_tooltip.len()].copy_from_slice(&wide_tooltip);
    |         ^^^^^^^^^
    |
    = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses
    = note: creating a misaligned reference is undefined behavior (even if that
reference is never dereferenced)
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)

For more information about this error, try `rustc --explain E0793`.
error: could not compile `tray-item` (lib) due to previous error

Consider ksni crate for Linux

Instead of gtk and libappindicator consider using ksni which implements dbus interfaces natively (libappindicator does it via C code anyway).
The advantage is much smaller dependency tree and the requirements for build environment.

Create new release

Creating an issue just as a reminder for myself to release a new version with the newly accepted PRs.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.