I need a list with only those apps that are currently open/running in Dash, the ones that have that small white arrow(s) on the left side of the icon.
Is there any way to get it?
I need a list with only those apps that are currently open/running in Dash, the ones that have that small white arrow(s) on the left side of the icon.
Is there any way to get it?
Interesting question.
As always, there are different ways to get a list of these applications, each of them with specific ad- and disadvantages.
Since only applications with a (mapped) window appear in the Launcher, using:
wmctrl -lp
(wmctrl
is not installed by default), we can get a list of opened windows and the process- id the windows belong to. The format of the output is:
0x05204641 0 12618 jacob-System-Product-Name verhaal (~) - gedit
where for us most important information is in:
0x05204641
); this is the window -id12618
); this is the process id (pid) the window belongs to, and,verhaal (~) - gedit
); this is the window name.Once we have the pid, we can look up the corresponding process name by the command:
ps -p <pid> -o comm=
We can script the steps above, and list the output(s) for existing windows, looking like (using python
):
{'gnome-terminal', 'nautilus', 'gedit', 'GuitarPro.exe', 'firefox', 'thunderbird', 'soffice.bin'}
This seems straightforward. However, as always, reality is a bit more complicated. There are a few exceptions and complications we need to take care of:
Idle
(python
IDE) or tkinter
are such windows.wmctrl
, but do not appear separately in Dash.LibreOffice
where all modules have the process name of soffice.bin
. At the same time, running the command soffice.bin
will not work. In case you need to identify the modules (Calc
, Writer
etc.) separately, you'd need to get additional information, from the window's name for example.gnome-terminal
, as it appears in the process list, as in the output of ps -e ww
. In 14.04, gnome-terminal
appears as gnome-terminal
, however, in 15.04 / 15.10 it shows: /usr/lib/gnome-terminal/gnome-terminal-server
. To fix the most important issues above, you need to:
add a check if the window is a "real" or "normal" window, checking with
xprop -id <window_id>
If the output includes the line:
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
The window is a valid window in the sense of the Unity Launcher
gnome-terminal
in 15.x
(assuming you want the presented process name to be gnome-terminal
) we need to add an exception, to rename the process name into gnome-terminal
if it appears as
/usr/lib/gnome-terminal/gnome-terminal-server
#!/usr/bin/env python3
import subprocess
import sys
try:
listed = sys.argv[1]
except IndexError:
listed = []
get = lambda cmd: subprocess.check_output(cmd).decode("utf-8").strip()
def check_wtype(w_id):
# check the type of window; only list "NORMAL" windows
return "_NET_WM_WINDOW_TYPE_NORMAL" in get(["xprop", "-id", w_id])
def get_process(w_id):
# get the name of the process, owning the window
proc = get(["ps", "-p", w_id, "-o", "comm="])
proc = "gnome-terminal" if "gnome-terminal" in proc else proc
return proc
wlist = [l.split() for l in subprocess.check_output(["wmctrl", "-lp"])\
.decode("utf-8").splitlines()]
validprocs = set([get_process(w[2]) for w in wlist if check_wtype(w[0]) == True])
if listed == "-list":
for p in validprocs:
print(p)
else:
print(validprocs)
The script needs wmctrl
:
sudo apt-get install wmctrl
copy the script above into an empty file, save it as get_running.py
run it by the command:
python3 /path/to/get_running.py
It will output like:
{'gnome-terminal', 'nautilus', 'gedit', 'GuitarPro.exe', 'firefox', 'thunderbird', 'soffice.bin'}
or, run with the argument -list
:
thunderbird
nautilus
gnome-terminal
firefox
gedit
GuitarPro.exe
soffice.bin
From your question, it is not completely clear what is exactly the purpose of the found list. If you need to have the application's name, as it appears in the interface ("readable" names), a completely different approach might be suited:
.desktop
file in /usr/share/applications
. In far most cases, we can conclude the process name and the interface name of the application from its .desktop
file. Using this information, we could relatively easy create a list of running GUI applications, presented by their "readable" name. Also in this case however, reality is also more complicated then theory, as explained here.
The way to do it with qdbus
and org.ayatana.bamf
interface.
List of open applications by .desktop
file:
$ qdbus org.ayatana.bamf /org/ayatana/bamf/matcher \
> org.ayatana.bamf.matcher.RunningApplicationsDesktopFiles
/usr/share/applications/compiz.desktop
/usr/share/applications/firefox.desktop
/usr/share/applications/x-terminal-emulator.desktop
Using org.ayatana.bamf.matcher.RunningApplications
and org.ayatana.bamf.view.Name
methods
$ qdbus org.ayatana.bamf /org/ayatana/bamf/matcher \
> org.ayatana.bamf.matcher.RunningApplications | \
> xargs -I {} qdbus org.ayatana.bamf {} org.ayatana.bamf.view.Name
Firefox Web Browser
MY CUSTOM TERMINAL
Compiz