Better Programming

Advice for programmers.

Follow publication

How I Made My Productivity App Open Faster by Adding It to the System Tray

A brief guide to debugging my Focus tool

Amine Ben hammou
Better Programming
Published in
4 min readJun 16, 2022

--

Photo by Austin Distel on Unsplash

In the previous article, I shared how I started working on a small productivity tool called focus.

The idea of the tool is simple:

  • I hit a keyboard shortcut anywhere on my computer.
  • A popup shows on the center of the screen containing a text input.
  • I type some idea/task I want to remember later, when I hit Enter.
  • The popup disappears.
  • All ideas I type are added to a text file. The path of that file is set by the environment variable FOCUS_TASKS_PATH.

I had a working version, but there was one problem: When I hit the keyboard shortcut, the popup takes about two seconds to open and render correctly. Let’s make it “pop up” faster.

Why Is It Slow? It’s Just a Text Input, Right?

From my understanding of Tauri’s process model, when I hit the shortcut, the following happens:

  • A core process is created. This is the process that runs the Rust code.
  • A webview process is created by the core process. This is the one running the frontend code.

You can think of a webview as a mini-browser that has everything needed to show a web page and handle interactions on it (parsing HTML, applying CSS, executing JavaScript, etc.). Plus it can communicate with the core process to run Rust code.

This explains why it takes time the start it (like it takes time to open Chrome or VSCode).

How to Make It Open Faster?

My idea is to open the app once and keep it running in the background so that when the shortcut is hit, we only show the window which should be faster than creating it from scratch. One way to do that is to add the app to the system tray (the section that has the small icons on the taskbar. You know the one that you close an app but still find its icon there telling you “I am still alive!”).

Adding the Application to the System Tray

By following the documentation, first, we need to specify the icon of our app on the system tray using the tauri.conf.json file, let's use the already existing Tauri icon (I may need to design a custom icon for this application, but not a priority for now).

Next, I modified the dependencies section of the Cargo.toml file to include the feature gtk-tray which is needed on my Linux distribution.

tauri = { version = "1.0.0-rc.11", features = ["api-all", "gtk-tray", "system-tray"] }

Now we need to edit the main.rs file to create the system tray and specify the menu items attached to it.

The make_tray function creates the system tray with a menu containing two items: Hide and Quit.

  • Initially, the application window is shown; I want to be able to hide it by clicking the Hide menu item. Then its text should become Show and clicking it should show the window again.
  • Clicking on the Quit menu item should close the application.

If I run the application now, I see the Tauri icon on the system tray. Clicking on it shows the menu with Hide and Quit items, but clicking them does nothing. To run some code when the items are clicked we should add an event handler using the on_system_tray_event method:

Then we define the handle_tray_event function:

Here’s the result:

System tray menu

Hiding the Window From the Frontend

The next step is to hide the window when Enter is typed on the input instead of closing the application. To do so, let's update the App component's code:

Now when I type something and hit Enter, the window is hidden but there are two problems:

  1. The menu item still shows Hide when I click the icon on the system tray.
  2. When the window is shown again, the text I typed last time is still there.

Let’s start by fixing the second problem which is easier. All we have to do is to set the content state to an empty string after invoking the add_task command.

The first problem is trickier. I didn’t find a way to change the menu item text using the JavaScript API. So it seems that I need to call Rust code to do that. Let’s create a new command hide_window:

And call it from the frontend:

Note that the hide_window command takes an argument app of type AppHandle, but we don't pass any argument when calling it from Javascript. Tauri will inject that argument automatically based on its type.

Show the Window With a Global Shortcut

So far, I was running a new instance of the application when typing the shortcut, but now I want to just show the hidden window and not open a whole new instance. Tauri offers a way to register global shortcuts and run custom code when they are pressed.

Let’s enable global shortcuts on tauri.conf.json. Here’s how to do that:

Then register the shortcut Alt+Enter by adding the following code to the main.tsx file:

Now the string Alt+Enter pressed! should be logged into the console every time I press Alt+Enter. But it doesn't work and I didn't know why… until I found this open issue on the tao repository: https://github.com/tauri-apps/tao/issues/307

Tao is the Rust library Tauri uses to create and manage windows. And according to that issue, global shortcuts don’t work properly on Linux. That’s why it’s not working for me!

So, if I want to continue working on this application, I need to implement a workaround for global shortcuts to work on Ubuntu. That’s what I will be doing in the next article.

See ya!

Sign up to discover human stories that deepen your understanding of the world.

--

--

Amine Ben hammou
Amine Ben hammou

Written by Amine Ben hammou

I am a software engineer with focus on web development and performance optimization.

Responses (1)

Write a response