Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

To have a "minimize window" option through right click on an icon in the Unity launcher (Ubuntu 14.04), I followed the detailed instructions here about changing a .desktop file and made a custom Firefox launcher in ~/.local/share/applications/ folder. The relevant part of the .desktop file is:

Actions=NewWindow;NewPrivateWindow;Minimize

[Desktop Action NewWindow]
Name=Open a New Window
Exec=firefox -new-window
OnlyShowIn=Unity;

[Desktop Action NewPrivateWindow]
Name=Open a New Private Window
Exec=firefox -private-window
OnlyShowIn=Unity;

[Desktop Action Minimize]
Name=Minimize Windows
Exec=sh /home/myusername/Documents/xdotool_sh/minimize.sh firefox
OnlyShowIn=Unity;

The desktop action "Minimize" invokes a simple shell script, minimize.sh that has the following content:

#/bin/bash
name=$1
for i in $(xdotool search --class "$name"); do
    xdotool windowminimize $i
done

The script uses xdotool, that can be installed from the official repositories, to find all the firefox windows, iterate over them and minimize them.

The script works and the launcher right menu option "Minimize Windows" works as well, but as soon as the windows are minimized, the mouse pointer gets in "busy" mode and stays like this for about 20 seconds (although the mouse actions are still responsive).

Does anyone know why starting a shell script from a right menu option in Unity could lead to this behaviour?

EDIT: Apparently the wait period is inevitable, as explained in Jacob Vlijm's answer. Since the mouse remains responsive, avoiding the transformation of the pointer in the spinning wheel is a partial esthetic workaround, as explained on askubuntu.

EDIT2: giving the system a fake window is a better solution, as explained by Jacob below.

share|improve this question
    
Hi Cosmin, I added another, pretty clean solution I think. – Jacob Vlijm Mar 11 at 7:22
    
Thank you Jacob. I was thinking about that kind of solution but did not know how it could be done. It is great that a solution exists. – Cosmin Saveanu Mar 11 at 8:16
up vote 15 down vote accepted

Excellent question.

The cause

Normally, when starting GUI applications from the Unity Launcher, the launcher waits for a window to appear. While waiting, it shows the "spinning wheel". It won't wait forever however; after about 20 seconds, the launcher assumes the window won't appear and gives up waiting.

1. The main command of an application's launcher

In a .desktop file, concerning the first Exec= line (the main command), you can tell the launcher to wait or not, in a line:

StartupNotify=true

to make it wait, or

StartupNotify=false

to make it not wait.

2. Quicklist items of a launcher

For possible quicklist (right-click) items of a launcher however, the default value is StartupNotify=true. Unfortunately, this value is fixed and cannot be changed by anything.

That means that if you start any command from right-clicking a launcher icon in the Unity Launcher, the launcher is expecting a window and waits for it, showing the spinning wheel.

The bottom line is that, although it can be explained, there seems to be no solution to the issue at the moment, other then creating a dedicated launcher for your script and add the line StartupNotify=false to the file.

The proof

You can test the behaviour yourself. Create two launchers:

[Desktop Entry]
Name=Test
Exec=sh /home/myusername/Documents/xdotool_sh/minimize.sh firefox
Type=Application
StartupNotify=true

and:

[Desktop Entry]
Name=Test
Exec=sh /home/myusername/Documents/xdotool_sh/minimize.sh firefox
Type=Application
StartupNotify=false

Save them as test1.desktop and test2.desktop, drag both launchers on to the Unity launcher. Click them and see the difference in behaviour.


Edit; if it really bothers you, feed Unity a fake window

If you have many scripts in quicklists, and/or it really bothers you, there is another cosmetic solution; we can fake, invisible (fully transparent) to show a window, to be included in your script. your script would then be (e.g.)

#/bin/bash
name=$1
for i in $(xdotool search --class "$name"); do
    xdotool windowminimize $i
done
fake_window

where the command fake_window will call our (fake-) window, making Unity end the spinning wheel.

How to set up

  1. Create, if it does not exist yet, the directory ~/bin
  2. Copy the script below into an empty file, save it as fake_window (no extension) in ~/bin and make it executable

    #!/usr/bin/env python3
    from gi.repository import Gtk
    from threading import Thread
    import time
    import subprocess
    
    """
    This is a self-destroying window, to "feed" Unity a fake-window, preventing
    the launcher to show a spinning wheel, waiting for a window to appear.
    Include the command to run this script at the end of the (your) script.
    """
    
    class FakeWin(Gtk.Window):
    
        def __init__(self):
            Gtk.Window.__init__(self, title="1526closeme")
            Thread(target = self.close).start()
    
        def close(self):
            t = 0
            while t < 150:
                time.sleep(0.2)
                try:
                    pid = subprocess.check_output(["pgrep", "-f", "fake_window"])\
                          .decode("utf-8").strip()
                    subprocess.Popen(["kill", pid])
                    break
                except subprocess.CalledProcessError:
                    pass
                t += 1
    
    def fakewindow():
        window = FakeWin()
        # make our window transparent
        window.set_opacity(0)
        window.set_default_size(0,0)
        window.show_all()
        Gtk.main()
    
    fakewindow()
    
  3. Add to the very end of your script the command:

    fake_window
    
  4. Log out and back in (or run source ~/.profile)

That's it, the wheel will now only spin for as long as the script runs.

Explanation

The script does create a minimalistic window. The window however is fully transparent and has a size of 0x0 pixels and is thus invisible. It will destroy itself instantly once it exists.

Calling the window at the end of your script, you will satisfy Unity's wish for a window, stopping the wheel to spin.

share|improve this answer
    
Thank you for the detailed explanation and edits on the question. Gives ideas about potential workarounds. – Cosmin Saveanu Mar 10 at 8:53
    
@Cocofifi you're welcome! – Jacob Vlijm Mar 10 at 8:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.