How to show (raise) all windows of an application?Bring all windows of the same application to front on focus in UnityWindow switcher (alt+tab) raises all windowsScript to Alt+Tab till application is foundHow can I bring all windows of an application to the front?Is there a way to add a window list on the panel in Unity?How to make Alt+Tab return to same application window as last used (Unity)Is there any way to open all instances of a particular application without having to click on its icon multiple times?Link minimize/maximize/on top between parent/child app windowsShow all open windows in 11.04?How can I bring all windows of an application to the front?How can I show all non-minimized windows?How can I open multiple windows in one application, and show them at the same time?Move semi- maximized windows across multiple (2 or more) monitorsHow can I use Devilspie2 to bring a window to the foreground when opened?How can I make wmctrl raise the most recently fosused window of an application?Moving Ubuntu WindowsBring all windows of the same application to front on focus in UnityIs there any way to crop windows (not images) in Ubuntu?

Can I Retrieve Email Addresses from BCC?

Freedom of speech and where it applies

Pronouncing Homer as in modern Greek

Resetting two CD4017 counters simultaneously, only one resets

What (else) happened July 1st 1858 in London?

Identify a stage play about a VR experience in which participants are encouraged to simulate performing horrific activities

For airliners, what prevents wing strikes on landing in bad weather?

How can I raise concerns with a new DM about XP splitting?

A known event to a history junkie

How to prevent YouTube from showing already watched videos?

Should my PhD thesis be submitted under my legal name?

How to check participants in at events?

Lifted its hind leg on or lifted its hind leg towards?

Is there an Impartial Brexit Deal comparison site?

Organic chemistry Iodoform Reaction

Meta programming: Declare a new struct on the fly

Can I rely on these GitHub repository files?

Stereotypical names

How to deal with or prevent idle in the test team?

A workplace installs custom certificates on personal devices, can this be used to decrypt HTTPS traffic?

What is the opposite of 'gravitas'?

What does the "3am" section means in manpages?

Hostile work environment after whistle-blowing on coworker and our boss. What do I do?

Is there a problem with hiding "forgot password" until it's needed?



How to show (raise) all windows of an application?


Bring all windows of the same application to front on focus in UnityWindow switcher (alt+tab) raises all windowsScript to Alt+Tab till application is foundHow can I bring all windows of an application to the front?Is there a way to add a window list on the panel in Unity?How to make Alt+Tab return to same application window as last used (Unity)Is there any way to open all instances of a particular application without having to click on its icon multiple times?Link minimize/maximize/on top between parent/child app windowsShow all open windows in 11.04?How can I bring all windows of an application to the front?How can I show all non-minimized windows?How can I open multiple windows in one application, and show them at the same time?Move semi- maximized windows across multiple (2 or more) monitorsHow can I use Devilspie2 to bring a window to the foreground when opened?How can I make wmctrl raise the most recently fosused window of an application?Moving Ubuntu WindowsBring all windows of the same application to front on focus in UnityIs there any way to crop windows (not images) in Ubuntu?













19















I have an application using multiple windows. How can I quickly bring all the windows of that application to the foreground?



When I scroll through the applications with the scroll-wheel it only shows one window. When going to the next window, the last window is brought to the background again.



When I click on the application icon, I get a full-screen overview of all the windows. I have to select each window manually and move my mouse across half the screen several times.



My best solution so far is minimizing all windows (Ctrl+Super+D) and then show the windows of my application using the scroll-wheel.



Is there a better solution?










share|improve this question
























  • @Joschua Bringing all windows of an application to the front is not too difficult, but how would you like to define the application? would a key combination+clicking an application's window do?

    – Jacob Vlijm
    Jan 5 '15 at 20:24












  • @Joschua or mayby more elegant, a key combo + 1st character of application name?

    – Jacob Vlijm
    Jan 5 '15 at 20:51











  • I think the behavior ist the same with all applications. I most often miss this feature with terminal windows, where I often have two or more windows open side by side. Then I switch to a full screen window (e.g. Firefox) and when I want to switch back to the two terminal windows it is kinda difficult. The best way I found so far is a mouse-middle-click on the Firefox application bar which brings Firefox to the background so that I have the two terminals at the front again. However this only works well, when There are not too many applications piled on top :D

    – peq
    Jan 5 '15 at 22:08











  • also @Joschua It would be possible to have a key combination to bring to front application window groups; press once -> all firefox windows show up, pres again -> all terminal windows show up etc. could be made really smooth. interesting. working on it. will take a little work though.

    – Jacob Vlijm
    Jan 5 '15 at 22:22












  • @JacobVlijm Sounds like the right direction.. :) What seems most important to me, is that a key combination plus clicking on the icon brings all windows of that application (for example, many terminals as peq mentioned) to the front, preferably spread out, so that they are non-overlapping.. (Maybe, something like this could become part of Unity?!)

    – Joschua
    Jan 6 '15 at 0:06
















19















I have an application using multiple windows. How can I quickly bring all the windows of that application to the foreground?



When I scroll through the applications with the scroll-wheel it only shows one window. When going to the next window, the last window is brought to the background again.



When I click on the application icon, I get a full-screen overview of all the windows. I have to select each window manually and move my mouse across half the screen several times.



My best solution so far is minimizing all windows (Ctrl+Super+D) and then show the windows of my application using the scroll-wheel.



Is there a better solution?










share|improve this question
























  • @Joschua Bringing all windows of an application to the front is not too difficult, but how would you like to define the application? would a key combination+clicking an application's window do?

    – Jacob Vlijm
    Jan 5 '15 at 20:24












  • @Joschua or mayby more elegant, a key combo + 1st character of application name?

    – Jacob Vlijm
    Jan 5 '15 at 20:51











  • I think the behavior ist the same with all applications. I most often miss this feature with terminal windows, where I often have two or more windows open side by side. Then I switch to a full screen window (e.g. Firefox) and when I want to switch back to the two terminal windows it is kinda difficult. The best way I found so far is a mouse-middle-click on the Firefox application bar which brings Firefox to the background so that I have the two terminals at the front again. However this only works well, when There are not too many applications piled on top :D

    – peq
    Jan 5 '15 at 22:08











  • also @Joschua It would be possible to have a key combination to bring to front application window groups; press once -> all firefox windows show up, pres again -> all terminal windows show up etc. could be made really smooth. interesting. working on it. will take a little work though.

    – Jacob Vlijm
    Jan 5 '15 at 22:22












  • @JacobVlijm Sounds like the right direction.. :) What seems most important to me, is that a key combination plus clicking on the icon brings all windows of that application (for example, many terminals as peq mentioned) to the front, preferably spread out, so that they are non-overlapping.. (Maybe, something like this could become part of Unity?!)

    – Joschua
    Jan 6 '15 at 0:06














19












19








19


9






I have an application using multiple windows. How can I quickly bring all the windows of that application to the foreground?



When I scroll through the applications with the scroll-wheel it only shows one window. When going to the next window, the last window is brought to the background again.



When I click on the application icon, I get a full-screen overview of all the windows. I have to select each window manually and move my mouse across half the screen several times.



My best solution so far is minimizing all windows (Ctrl+Super+D) and then show the windows of my application using the scroll-wheel.



Is there a better solution?










share|improve this question
















I have an application using multiple windows. How can I quickly bring all the windows of that application to the foreground?



When I scroll through the applications with the scroll-wheel it only shows one window. When going to the next window, the last window is brought to the background again.



When I click on the application icon, I get a full-screen overview of all the windows. I have to select each window manually and move my mouse across half the screen several times.



My best solution so far is minimizing all windows (Ctrl+Super+D) and then show the windows of my application using the scroll-wheel.



Is there a better solution?







unity window-manager






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '16 at 14:56









Jacob Vlijm

65.5k9130226




65.5k9130226










asked Apr 11 '14 at 15:43









peqpeq

665610




665610












  • @Joschua Bringing all windows of an application to the front is not too difficult, but how would you like to define the application? would a key combination+clicking an application's window do?

    – Jacob Vlijm
    Jan 5 '15 at 20:24












  • @Joschua or mayby more elegant, a key combo + 1st character of application name?

    – Jacob Vlijm
    Jan 5 '15 at 20:51











  • I think the behavior ist the same with all applications. I most often miss this feature with terminal windows, where I often have two or more windows open side by side. Then I switch to a full screen window (e.g. Firefox) and when I want to switch back to the two terminal windows it is kinda difficult. The best way I found so far is a mouse-middle-click on the Firefox application bar which brings Firefox to the background so that I have the two terminals at the front again. However this only works well, when There are not too many applications piled on top :D

    – peq
    Jan 5 '15 at 22:08











  • also @Joschua It would be possible to have a key combination to bring to front application window groups; press once -> all firefox windows show up, pres again -> all terminal windows show up etc. could be made really smooth. interesting. working on it. will take a little work though.

    – Jacob Vlijm
    Jan 5 '15 at 22:22












  • @JacobVlijm Sounds like the right direction.. :) What seems most important to me, is that a key combination plus clicking on the icon brings all windows of that application (for example, many terminals as peq mentioned) to the front, preferably spread out, so that they are non-overlapping.. (Maybe, something like this could become part of Unity?!)

    – Joschua
    Jan 6 '15 at 0:06


















  • @Joschua Bringing all windows of an application to the front is not too difficult, but how would you like to define the application? would a key combination+clicking an application's window do?

    – Jacob Vlijm
    Jan 5 '15 at 20:24












  • @Joschua or mayby more elegant, a key combo + 1st character of application name?

    – Jacob Vlijm
    Jan 5 '15 at 20:51











  • I think the behavior ist the same with all applications. I most often miss this feature with terminal windows, where I often have two or more windows open side by side. Then I switch to a full screen window (e.g. Firefox) and when I want to switch back to the two terminal windows it is kinda difficult. The best way I found so far is a mouse-middle-click on the Firefox application bar which brings Firefox to the background so that I have the two terminals at the front again. However this only works well, when There are not too many applications piled on top :D

    – peq
    Jan 5 '15 at 22:08











  • also @Joschua It would be possible to have a key combination to bring to front application window groups; press once -> all firefox windows show up, pres again -> all terminal windows show up etc. could be made really smooth. interesting. working on it. will take a little work though.

    – Jacob Vlijm
    Jan 5 '15 at 22:22












  • @JacobVlijm Sounds like the right direction.. :) What seems most important to me, is that a key combination plus clicking on the icon brings all windows of that application (for example, many terminals as peq mentioned) to the front, preferably spread out, so that they are non-overlapping.. (Maybe, something like this could become part of Unity?!)

    – Joschua
    Jan 6 '15 at 0:06

















@Joschua Bringing all windows of an application to the front is not too difficult, but how would you like to define the application? would a key combination+clicking an application's window do?

– Jacob Vlijm
Jan 5 '15 at 20:24






@Joschua Bringing all windows of an application to the front is not too difficult, but how would you like to define the application? would a key combination+clicking an application's window do?

– Jacob Vlijm
Jan 5 '15 at 20:24














@Joschua or mayby more elegant, a key combo + 1st character of application name?

– Jacob Vlijm
Jan 5 '15 at 20:51





@Joschua or mayby more elegant, a key combo + 1st character of application name?

– Jacob Vlijm
Jan 5 '15 at 20:51













I think the behavior ist the same with all applications. I most often miss this feature with terminal windows, where I often have two or more windows open side by side. Then I switch to a full screen window (e.g. Firefox) and when I want to switch back to the two terminal windows it is kinda difficult. The best way I found so far is a mouse-middle-click on the Firefox application bar which brings Firefox to the background so that I have the two terminals at the front again. However this only works well, when There are not too many applications piled on top :D

– peq
Jan 5 '15 at 22:08





I think the behavior ist the same with all applications. I most often miss this feature with terminal windows, where I often have two or more windows open side by side. Then I switch to a full screen window (e.g. Firefox) and when I want to switch back to the two terminal windows it is kinda difficult. The best way I found so far is a mouse-middle-click on the Firefox application bar which brings Firefox to the background so that I have the two terminals at the front again. However this only works well, when There are not too many applications piled on top :D

– peq
Jan 5 '15 at 22:08













also @Joschua It would be possible to have a key combination to bring to front application window groups; press once -> all firefox windows show up, pres again -> all terminal windows show up etc. could be made really smooth. interesting. working on it. will take a little work though.

– Jacob Vlijm
Jan 5 '15 at 22:22






also @Joschua It would be possible to have a key combination to bring to front application window groups; press once -> all firefox windows show up, pres again -> all terminal windows show up etc. could be made really smooth. interesting. working on it. will take a little work though.

– Jacob Vlijm
Jan 5 '15 at 22:22














@JacobVlijm Sounds like the right direction.. :) What seems most important to me, is that a key combination plus clicking on the icon brings all windows of that application (for example, many terminals as peq mentioned) to the front, preferably spread out, so that they are non-overlapping.. (Maybe, something like this could become part of Unity?!)

– Joschua
Jan 6 '15 at 0:06






@JacobVlijm Sounds like the right direction.. :) What seems most important to me, is that a key combination plus clicking on the icon brings all windows of that application (for example, many terminals as peq mentioned) to the front, preferably spread out, so that they are non-overlapping.. (Maybe, something like this could become part of Unity?!)

– Joschua
Jan 6 '15 at 0:06











4 Answers
4






active

oldest

votes


















21





+50









EDIT -new answer-



The answer(s) below is/are still totally valid, and so the suggested options. Ongoing insight however made me add this option to use the indicator below, which is probably the most elegant solution.



As such, it should probably replace option 5 (using a .desktop file).



Simply choose the application from the list, and all windows of the corresponding application (present on the current viewport) will raise:



enter image description here



How to use



from ppa:



sudo add-apt-repository ppa:vlijm/upfront
sudo apt-get update
sudo apt-get install upfront


...or manually:



#!/usr/bin/env python3
import signal
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GObject
import time
from threading import Thread
import os
import subprocess
import getpass

currpath = os.path.dirname(os.path.realpath(__file__))

class Indicator():
def __init__(self):
self.app = 'raise_apps'
iconpath = os.path.join(currpath, "raise.png")
self.indicator = AppIndicator3.Indicator.new(
self.app, iconpath,
AppIndicator3.IndicatorCategory.OTHER)
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
self.indicator.set_menu(self.create_menu())
# the thread:
self.update = Thread(target=self.check_recent)
# daemonize the thread to make the indicator stopable
self.update.setDaemon(True)
self.update.start()

def create_menu(self):
# creates the (initial) menu
self.menu = Gtk.Menu()
# separator
initial = Gtk.MenuItem("Fetching list...")
menu_sep = Gtk.SeparatorMenuItem()
self.menu.append(initial)
self.menu.append(menu_sep)
# item_quit.show()
self.menu.show_all()
return self.menu

def raise_wins(self, *args):
index = self.menu.get_children().index(self.menu.get_active())
selection = self.menu_items2[index][1]
for w in selection:
execute(["wmctrl", "-ia", w])

def set_new(self):
# update the list, appearing in the menu
for i in self.menu.get_children():
self.menu.remove(i)
for app in self.menu_items2:

sub = Gtk.MenuItem(app[0])
self.menu.append(sub)
sub.connect('activate', self.raise_wins)
# separator
menu_sep = Gtk.SeparatorMenuItem()
self.menu.append(menu_sep)
# quit
item_quit = Gtk.MenuItem('Quit')
item_quit.connect('activate', self.stop)
self.menu.append(item_quit)
self.menu.show_all()

def get_apps(self):
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
# windows on current viewport
relevant = [w for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
# pids
pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
return [m for m in matches if m[1]]

def check_recent(self):
self.menu_items1 = []
while True:
time.sleep(4)
self.menu_items2 = self.get_apps()
for app in self.menu_items2:
app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
if self.menu_items2 != self.menu_items1:
GObject.idle_add(
self.set_new,
priority=GObject.PRIORITY_DEFAULT
)
self.menu_items1 = self.menu_items2

def stop(self, source):
Gtk.main_quit()

def get(command):
return subprocess.check_output(command).decode("utf-8")

def execute(command):
subprocess.Popen(command)

Indicator()
GObject.threads_init()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()



  • The indicator needs wmctrl



    sudo apt-get wmctrl


  • Copy the indicator into an empty file, save it as raise_apps.py



  • Copy the image below, save it exactly named raise.png in one and the same directory as the indicator.



    enter image description here




  • Then simply run it by the command:



    python3 /path/to/raise_apps.py




  • Add if you want to Startup Applications:



    /bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py" 



OLD ANSWER:



About the question



With the right tools, it is not very complicated to "just" raise all windows of an application. It is a bit more complicated to make sure only the windows of the current viewport are raised. The real challenge however is to find a convenient way to make the action available to the user.



Below five options to take care of that, to show how it can be done. All options are ready to be used. The last option however is kind of experimental; it works fine but has a few minor cosmetic downsides, as explained in the description of the option. I added it nevertheless as a concept.



Spreading the windows automatically in a non- overlapping way, as suggested in a comment, seems not a practical idea to me; if you work in an (application-wise) grouped window setup, the script would possibly unwantedly rearrange windows.



How to use



For all options you need to:




  • install wmctrl if it is not yet on your system:



    sudo apt-get install wmctrl



  • create, if it does not exist yet, the directory:



    ~/bin


    (explanation: the directory ~/bin is in $PATH, so you can run executables by their name)



  • Copy the script, corresponding to the option, paste it into an empty file, save it as raise_app (no extension) in ~/bin and make it executable


In the separate options, possible additional steps will be explained.



Option 1: choose the application by entering one or more characters



  • Press a key combination, a zenity window will appear

  • Enter one or more characters of the application's name in the entry box

  • Press enter

This will make all windows of the matching application (on the current viewport) come to front.



raise all gnome-terminal windows on the current viewport:



enter image description here





enter image description here



How to use:



  • Do the set up as described in "How to use"


  • Test-run it by the command:



    raise_app


  • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


The script:



#!/usr/bin/env python3
import subprocess
import getpass

def get(command):
return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
subprocess.Popen(["/bin/bash", "-c", command])
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
# ask user for first characters
try:
arg = get('zenity --entry --text "first characters" --title "application"').strip()
except subprocess.CalledProcessError:
pass
# raise matching windows
try:
[execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
except (subprocess.CalledProcessError, NameError):
pass






Option 2: cycle through applications and raise their windows with a key combination:



Let's say I have the script below under a key combination Alt+1. I have several windows open of:



  • firefox

  • gnome-terminal

  • nautilus

The current state:



enter image description here



I press once Alt+1, all nautilus windows are raised:



<image>



I press again Alt+1, all firefox windows are raised:



<image>



I press again Alt+1, all gnome-terminal windows are raised again, the cycle starts over:



<image>



How to use



  • Do the set up as described in "How to use"


  • Add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command



    raise_app


Then cycle through your applications with grouped application windows with your key combination.



The script:



#!/usr/bin/env python3
import subprocess
import getpass

include_single = True # set to False if you only want to cycle through apps with multiple windows

def get(command):
return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
subprocess.Popen(["/bin/bash", "-c", command])

def get_frontmost():
cmd = "xprop -root"
frontmost = [l for l in get(cmd).splitlines() if
"ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
return frontmost[:2]+"0"+frontmost[2:]
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
# create application list to cycle through
if include_single == False:
pre = [it[0] for it in windows]
apps = sorted(list(set([it for it in pre if pre.count(it) > 1])))
else:
apps = sorted(list(set([it[0] for it in windows])))
if len(apps) == 0:
pass
else:
# get the frontmost window as a last itm in the cycle
front = get_frontmost()
front_pid = [l.split()[2] for l in get("wmctrl -lp").splitlines() if front in l][0]
last_infront = get("ps -u "+getpass.getuser()+" | grep "+front_pid).split()[-1]
# determine next apllication to raise
if not last_infront in apps or last_infront == apps[-1]:
arg = apps[0]
print(arg)
else:
arg = apps[apps.index(last_infront)+1]
# raise matching windows
try:
[execute("wmctrl -ia "+item[1]) for item in windows if item[0] == arg]
except (subprocess.CalledProcessError, NameError):
pass






Option 3: press key combination + click on launcher icon -or- application window to raise all windows on the current viewport



This is probably the option that is closest to what is described in the question / comment.



Let's say I have a messy desktop with three nautilus windows buried under other windows.



<image>



To raise all nautilus windows (example shortcut: Alt+1):



  • Press Alt+1, release (!)


  • Within 3 seconds, either:



    click on the application's icon in the launcher



    <image>



    or:



    click on one of the application's windows



    <image>



    result:



    <image>




How to use:



  • Do the set up as described in "How to use"


  • Test-run it by the command:



    raise_app


  • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


Then:




  • Press your key combination and within 3 seconds, either:



    • click on the application's icon in the launcher

    • click on one of the application's windows


The script



#!/usr/bin/env python3
import subprocess
import getpass
import time

def get(command):
return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
subprocess.Popen(["/bin/bash", "-c", command])

def get_frontmost():
cmd = "xprop -root"
frontmost = [l for l in get(cmd).splitlines() if
"ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
return frontmost[:2]+"0"+frontmost[2:]

# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# get window data for various purposes
w_data = get("wmctrl -lpG").splitlines()
non_windows = sum([[l.split()[0] for l in w_data if it in l]
for it in ("unity-launcher", "unity-panel", "unity-dash", "Hud")], [])
# get id of current window
curr_window = get_frontmost()
# user gets 3 seconds to pick an application window (or launcher icon)
t = 0
while t < 4:
w_id1 = get_frontmost()
time.sleep(1)
w_id2 = get_frontmost()
if w_id1 == w_id2 or w_id2 in non_windows+[curr_window]:
t = t+1
else:
new_frontmost = w_id2
break
# raise
try:
pid = [l.split()[2] for l in w_data if new_frontmost in l]
wl_data = [l.split() for l in w_data]
raise_windows = [l[0] for l in wl_data if pid[0] == l[2] and
0 < int(l[3]) < res[0] and 0 < int(l[4]) < res[1]]
[execute("wmctrl -ia "+item) for item in raise_windows]
except NameError:
pass





Option 4: a key combination calls an option list, showing the number of windows per application on the current viewport



This one turned out to be more convenient then I assumed:



Pressing the (again example-) key combination Alt+1 calls a zenity window, listing all applications and the number of their windows on the current viewport:



enter image description here



Simply pressing the or arrows will bring you to the right option. Press Enter and all windows of the chosen application are raised.



How to use:



  • Do the set up as described in "How to use"


  • Test-run it by the command:



    raise_app


  • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


The script



#!/usr/bin/env python3
import subprocess
import getpass

def get(command):
return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
subprocess.Popen(["/bin/bash", "-c", command])
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
# preparing zenity optionlist
apps = [item[0] for item in windows]
# prevent multiple zenity windows
if apps.count("zenity") > 1:
pass
elif apps.count("zenity") > 0:
execute('zenity --info --text "Another Zenity window is open already"')
# preventing empty windowlist
elif len(apps) > 0:
applist = [[app, str(apps.count(app))] for app in set(apps)]
applist.sort(key=lambda x: x[1])
# calling zenity window
try:
arg = get('zenity --list --text "Choose an application" '+
'--title "Current windows" '+
'--column "application" '+
'--column "windows" '+
'--height 250 '+
'--width 250 '+
(" ").join(sum(applist, [])))
except subprocess.CalledProcessError:
pass
# raise matching windows
try:
[execute("wmctrl -ia "+item[1])
for item in windows if arg.startswith(item[0])]
except (subprocess.CalledProcessError, NameError):
pass
else:
execute('zenity --info --text "No windows to list"')






Option 5: raise windows of running applications from a launcher icon



This option exists of a launcher icon, with the currently running applications in a quicklist. Choose one, and all windows of the applications will be raised.



enter image description here



The launcher is automatically updated when the list of running applications (on the current viewport) changes. The quicklist shows a different list on other viewports, where windows of other applications are opened (will take 1-2 seconds to adapt).





As mentioned, although fully functional, this option is a meant as a concept. It has a few minor cosmetic downsides as it is. The most important:



  • The cursor "wheel" keeps spinning for a few seconds after an action. Although it does not effect the functionality, it is a cosmetic downside.

  • It takes 1-2 seconds for the applicationlist in the launcher icon to be updated after the list of running applications changes.

Furthermore the setup is slightly more complicated (although explained in detail below):



How to use



Below you will find:



two scripts / an icon / a .desktop file



  1. Prepare the setup as in "How to use", save the first (main-) script as raise_app in ~/bin


  2. Save the icon below (right-click, save as) as raise.png



    <icon>




  3. Copy the .desktop file into an empty file, edit the line



     Icon=/path/to/raise.png


    to the real path to the icon (paths with spaces between quotes)

    Save it as raise.desktop in ~/.local/share/applications



  4. Drag the .desktop file to the launcher to add it


  5. copy the second script, paste it into an empty file, save it as update_apps in ~/bin, make it executable.


  6. Add the following command to your startup applications (Dash > Startup Applications > Add):



    update_apps


  7. Log out and back in to make it work.

The first script



#!/usr/bin/env python3
import subprocess
import getpass
import sys

arg = sys.argv[1]

def get(command):
return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
subprocess.Popen(["/bin/bash", "-c", command])
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
try:
[execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
except (subprocess.CalledProcessError, NameError):
pass


The second script



#!/usr/bin/env python3
import subprocess
import getpass
import time
import os

dtfile = os.environ["HOME"]+"/.local/share/applications/raise.desktop"

def get(command):
return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
subprocess.Popen(["/bin/bash", "-c", command])
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
def applist():
try:
w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
except subprocess.CalledProcessError:
return []
else:
return set([app[0] for app in windows])

def update_dtfile(applications, text):
actionline = "Actions="+(";").join(applications)+";n"
with open(dtfile) as src:
lines = src.readlines()
lines = lines[:[i for i in range(len(lines))
if lines[i].startswith("Actions=")][0]]+[actionline]
for item in text:
for it in item:
lines.append(it)
with open(dtfile, "wt") as out:
for line in lines:
out.write(line)

while True:
apps1 = applist()
time.sleep(1)
apps2 = applist()
if apps1 != apps2:
text = [["[Desktop Action "+it+"]n", "Name="+it+"n",
"Exec=raise_app "+it+"n", "OnlyShowIn=Unity;nn",
]for it in apps2]
update_dtfile(apps2, text)


The .desktop file



[Desktop Entry]
Name=Raise application windows
Comment=Raise groups of windows
Icon=/path/to/raise.png
Terminal=false
Type=Application
Version=1.0

Actions=






Brief Explanation



All solutions above use wmctrl to create a window list, using the wmctrl -lpG command. This command produces lines, looking like:



0x044000b3 0 3429 65 24 1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox


These lines include:



  • 1st column: the window's id (that we can use to raise it)

  • 3rd column: the pid that owns the window.

  • 4th / 5th column: the window's geometry x-y (that we use to see if the window is on the current viewport, i.c.w xrandr)

The pid is looked up in the output of ps -u <username> to get a "user-readable" identification (name) of the application.

Thus we can allocate windows to applications. Subsequently we can raise the windows of a given application in a for loop with the command wmctrl -ia.



In option 3

the script starts a 3- second "waiting" loop, using the xprop -root command repeatedly to see if there is any change in what is the frontmost window; this will happen if the user either clicks on a launcher icon to raise an application's window, or clicks on a window directly. If so, the while- loop breaks and looks up the "new" frontmost application, and subsequently raises all other windows of that application.






share|improve this answer

























  • I agree, and thanks again for all your effort! :) || There's a weird thing that I didn't notice before. Sometimes after using the Option 2 script, when an application window is focused (that is not maximized) and I click on another window that is visible "below", the application below below doesn't get the focus.

    – Joschua
    Jan 8 '15 at 22:47











  • @Joschua the OP of this question: askubuntu.com/questions/575830/… attended me of a bug that was introduced at the latest "feature" update. True/False were mixed up, causing the script to crash when no applications have more then one window. If you use option2, please update to the latest version.

    – Jacob Vlijm
    Jan 21 '15 at 19:22











  • Option 1 not working for me on ubuntu xenial. something@something:~/bin$ ./raise_app Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged. I was trying to open terminal windows. Nothing happened.

    – xtrinch
    Sep 17 '16 at 12:33











  • @Nirri what application name did you use? The message is quite normal if a zenity window runs without a Gtk parent. "Discouraged" is not an error.

    – Jacob Vlijm
    Sep 17 '16 at 12:39












  • First chars of terminal. It works - kind of - it raises a window of any app - but only one of them, not all of them as expected @user72216

    – xtrinch
    Sep 17 '16 at 12:42


















1














There is Super+W shortcut which will show expo of all the currently open windows, though that will include other applications. This comes by default, and doesn't require any changes, so perhaps it's a simplest option available.



Among other things, you could position windows on right and left halves of the screen with Ctrl+Super+Left/Right buttons, and switch between them with Alt+~ (tilde, the one next to number one key).






share|improve this answer

























  • That doesn't bring all the windows of an application to the top though. You can see them, but you can't use them without having to click a lot.

    – Joschua
    Jan 8 '15 at 11:49



















1














If you press Alt+Tab to cycle through applications, and you get to one with multiple windows, just keep holding the alt key down and after about 1 full second the icon will be replaced with a view of all of the windows for that application.



That may or may not be what you're looking for, but it works for me and is a ton simpler, so I figured I'd share the option!






share|improve this answer


















  • 1





    You can also press the down arrow key to have the application windows show up straight away.

    – Kris
    Aug 2 '16 at 16:12


















0














I took @JacobVlijm's raise_apps.py script and made some enhancements to it, including making it more robust.



Specifically, I had found that after a day or two, @JacobVlijm's script would stop working, and I'd have to manually the script, to get it working again. In retrospect, my best guess is that the numerous calls to xrandr eventually cause issues.



Anyways, I adapted his code, increased the polling frequency from 5 seconds to every 1 second, as it doesn't use much CPU anyways, and made it more robust. I can typically have it running for days/weeks without issues.



One caveat is that I only call xrandr once during startup, to get screen resolution dimensions. So if you change your screen resolution (e.g. from 1920x1080 to some other resolution), you'll probably want to manually restart raise-apps.py so that it will pick up the new resolution. Personally, I never change my screen resolution, so this is a non-issue for me. Additionally, I have strong reason to believe that too many calls to xrandr were what was causing @JacobVlijm's version of the script to stop working after a day or two, so I would strongly recommend not simply putting the numerous calls to xrandr back in..



BTW, you need to place the raise.png image in the /usr/local/icons/ directory. Or if you want to put raise.png in a different directory make the appropriate change to the script, so that the script can find the image file.



Hopefully, Ubuntu will integrate this type of 'raise all windows' functionality into their system sooner than later as it's very useful:



#!/usr/bin/python2
#
# Note to self:
# You need to add raise.png to /usr/local/icons/ directory.
#
# This script was taken from: https://askubuntu.com/questions/446521/how-to-show-raise-all-windows-of-an-application,
# (@JacobVlijm's answer), and then improved to fix some
# issues, that were causing it to stop working after a day or two.
#
#
from __future__ import print_function

from sys import stderr, exit
import signal
import gi

gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GObject, GLib

import logging
import logging.handlers

import time
import os
import subprocess
import getpass

logger = logging.getLogger('MyLogger')
logger.setLevel(logging.DEBUG)

log_handler = logging.handlers.SysLogHandler(address='/dev/log')

logger.addHandler(log_handler)


currpath = os.path.dirname(os.path.realpath(__file__))

class Indicator():
def __init__(self):
self.app = 'raise-apps'
iconpath = '/usr/local/icons/raise.png'
self.indicator = AppIndicator3.Indicator.new(
self.app, iconpath,
AppIndicator3.IndicatorCategory.OTHER)
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)

self.prev_menu_item_names = []
self.menu_items = []

res_output = get("xrandr").split()
if (len(res_output) == 0):
logger.error("raise-apps.py: invocation of xrandr failed! Unable to continue..")
exit(-1)

idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
(self.screen_width, self.screen_height) = res
logger.info("raise-apps.py: screen resolution is %s x %s" % (self.screen_width, self.screen_height))

self.indicator.set_menu(self.create_menu())

GLib.timeout_add_seconds(1.0, self.check_recent)

def create_menu(self):
# creates the (initial) menu
self.menu = Gtk.Menu()
# separator
initial = Gtk.MenuItem("Fetching list...")
menu_sep = Gtk.SeparatorMenuItem()
self.menu.append(initial)
self.menu.append(menu_sep)

self.menu.show_all()
return self.menu

def raise_wins(self, *args):
index = self.menu.get_children().index(self.menu.get_active())
selection = self.menu_items[index][1]
for w in selection:
execute(["wmctrl", "-ia", w])

def set_new(self):
# update the list, appearing in the menu
for i in self.menu.get_children():
self.menu.remove(i)
for app in self.menu_items:

sub = Gtk.MenuItem(app[0])
self.menu.append(sub)
sub.connect('activate', self.raise_wins)
# separator
menu_sep = Gtk.SeparatorMenuItem()
self.menu.append(menu_sep)

# quit
item_quit = Gtk.MenuItem('Quit')
item_quit.connect('activate', self.stop)
self.menu.append(item_quit)
self.menu.show_all()

def get_apps(self):
# creating window list on current viewport / id's / application names
w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
# windows on current viewport
relevant = [w for w in w_data if 0 < int(w[3]) < self.screen_width and 0 < int(w[4]) < self.screen_height]
# pids
pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
return [m for m in matches if m[1]]

def check_recent(self):
# print("in check_recent()", file=stderr)
self.menu_items = self.get_apps()
for app in self.menu_items:
app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
# check if menu items have changed:
has_changed = len(self.menu_items) != len(self.prev_menu_item_names)
if (not has_changed):
for i in range(len(self.menu_items)):
if self.prev_menu_item_names[i] != self.menu_items[i][0]:
has_changed = True
break

if has_changed:
GObject.idle_add(
self.set_new,
priority=GObject.PRIORITY_DEFAULT)

self.prev_menu_item_names = []
for item in self.menu_items:
self.prev_menu_item_names.append(item[0])

GLib.timeout_add_seconds(1.0, self.check_recent)


def stop(self, source):
Gtk.main_quit()


def recreate_menu(self, *args):
logger.info("in recreate_menu()")
self.prev_menu_item_names = []
self.menu_items = []

self.menu_items = self.get_apps()
for app in self.menu_items:
app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]

GObject.idle_add(
self.set_new,
priority=GObject.PRIORITY_DEFAULT)

self.prev_menu_item_names = []
for item in self.menu_items:
self.prev_menu_item_names.append(item[0])


def get(command):
# enable to get a feel for what this app is doing..
# print("get", command, file=stderr)
try:
return subprocess.check_output(command).decode("utf-8")

except subprocess.CalledProcessError as e:
logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
return ""

except OSError as e:
logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
return ""

def execute(command):
# enable to get a feel for what this app is doing..
# print("exec", command, file=stderr)
try:
subprocess.call(command)

except subprocess.CalledProcessError as e:
logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
return ""
except OSError as e:
logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
return ""


logger.info("(raise-apps.py is starting up..)")
Indicator()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()





share|improve this answer






















    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "89"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f446521%2fhow-to-show-raise-all-windows-of-an-application%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    21





    +50









    EDIT -new answer-



    The answer(s) below is/are still totally valid, and so the suggested options. Ongoing insight however made me add this option to use the indicator below, which is probably the most elegant solution.



    As such, it should probably replace option 5 (using a .desktop file).



    Simply choose the application from the list, and all windows of the corresponding application (present on the current viewport) will raise:



    enter image description here



    How to use



    from ppa:



    sudo add-apt-repository ppa:vlijm/upfront
    sudo apt-get update
    sudo apt-get install upfront


    ...or manually:



    #!/usr/bin/env python3
    import signal
    import gi
    gi.require_version('Gtk', '3.0')
    gi.require_version('AppIndicator3', '0.1')
    from gi.repository import Gtk, AppIndicator3, GObject
    import time
    from threading import Thread
    import os
    import subprocess
    import getpass

    currpath = os.path.dirname(os.path.realpath(__file__))

    class Indicator():
    def __init__(self):
    self.app = 'raise_apps'
    iconpath = os.path.join(currpath, "raise.png")
    self.indicator = AppIndicator3.Indicator.new(
    self.app, iconpath,
    AppIndicator3.IndicatorCategory.OTHER)
    self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
    self.indicator.set_menu(self.create_menu())
    # the thread:
    self.update = Thread(target=self.check_recent)
    # daemonize the thread to make the indicator stopable
    self.update.setDaemon(True)
    self.update.start()

    def create_menu(self):
    # creates the (initial) menu
    self.menu = Gtk.Menu()
    # separator
    initial = Gtk.MenuItem("Fetching list...")
    menu_sep = Gtk.SeparatorMenuItem()
    self.menu.append(initial)
    self.menu.append(menu_sep)
    # item_quit.show()
    self.menu.show_all()
    return self.menu

    def raise_wins(self, *args):
    index = self.menu.get_children().index(self.menu.get_active())
    selection = self.menu_items2[index][1]
    for w in selection:
    execute(["wmctrl", "-ia", w])

    def set_new(self):
    # update the list, appearing in the menu
    for i in self.menu.get_children():
    self.menu.remove(i)
    for app in self.menu_items2:

    sub = Gtk.MenuItem(app[0])
    self.menu.append(sub)
    sub.connect('activate', self.raise_wins)
    # separator
    menu_sep = Gtk.SeparatorMenuItem()
    self.menu.append(menu_sep)
    # quit
    item_quit = Gtk.MenuItem('Quit')
    item_quit.connect('activate', self.stop)
    self.menu.append(item_quit)
    self.menu.show_all()

    def get_apps(self):
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
    # windows on current viewport
    relevant = [w for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # pids
    pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
    matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
    return [m for m in matches if m[1]]

    def check_recent(self):
    self.menu_items1 = []
    while True:
    time.sleep(4)
    self.menu_items2 = self.get_apps()
    for app in self.menu_items2:
    app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
    if self.menu_items2 != self.menu_items1:
    GObject.idle_add(
    self.set_new,
    priority=GObject.PRIORITY_DEFAULT
    )
    self.menu_items1 = self.menu_items2

    def stop(self, source):
    Gtk.main_quit()

    def get(command):
    return subprocess.check_output(command).decode("utf-8")

    def execute(command):
    subprocess.Popen(command)

    Indicator()
    GObject.threads_init()
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    Gtk.main()



    • The indicator needs wmctrl



      sudo apt-get wmctrl


    • Copy the indicator into an empty file, save it as raise_apps.py



    • Copy the image below, save it exactly named raise.png in one and the same directory as the indicator.



      enter image description here




    • Then simply run it by the command:



      python3 /path/to/raise_apps.py




    • Add if you want to Startup Applications:



      /bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py" 



    OLD ANSWER:



    About the question



    With the right tools, it is not very complicated to "just" raise all windows of an application. It is a bit more complicated to make sure only the windows of the current viewport are raised. The real challenge however is to find a convenient way to make the action available to the user.



    Below five options to take care of that, to show how it can be done. All options are ready to be used. The last option however is kind of experimental; it works fine but has a few minor cosmetic downsides, as explained in the description of the option. I added it nevertheless as a concept.



    Spreading the windows automatically in a non- overlapping way, as suggested in a comment, seems not a practical idea to me; if you work in an (application-wise) grouped window setup, the script would possibly unwantedly rearrange windows.



    How to use



    For all options you need to:




    • install wmctrl if it is not yet on your system:



      sudo apt-get install wmctrl



    • create, if it does not exist yet, the directory:



      ~/bin


      (explanation: the directory ~/bin is in $PATH, so you can run executables by their name)



    • Copy the script, corresponding to the option, paste it into an empty file, save it as raise_app (no extension) in ~/bin and make it executable


    In the separate options, possible additional steps will be explained.



    Option 1: choose the application by entering one or more characters



    • Press a key combination, a zenity window will appear

    • Enter one or more characters of the application's name in the entry box

    • Press enter

    This will make all windows of the matching application (on the current viewport) come to front.



    raise all gnome-terminal windows on the current viewport:



    enter image description here





    enter image description here



    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    The script:



    #!/usr/bin/env python3
    import subprocess
    import getpass

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # ask user for first characters
    try:
    arg = get('zenity --entry --text "first characters" --title "application"').strip()
    except subprocess.CalledProcessError:
    pass
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
    except (subprocess.CalledProcessError, NameError):
    pass






    Option 2: cycle through applications and raise their windows with a key combination:



    Let's say I have the script below under a key combination Alt+1. I have several windows open of:



    • firefox

    • gnome-terminal

    • nautilus

    The current state:



    enter image description here



    I press once Alt+1, all nautilus windows are raised:



    <image>



    I press again Alt+1, all firefox windows are raised:



    <image>



    I press again Alt+1, all gnome-terminal windows are raised again, the cycle starts over:



    <image>



    How to use



    • Do the set up as described in "How to use"


    • Add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command



      raise_app


    Then cycle through your applications with grouped application windows with your key combination.



    The script:



    #!/usr/bin/env python3
    import subprocess
    import getpass

    include_single = True # set to False if you only want to cycle through apps with multiple windows

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])

    def get_frontmost():
    cmd = "xprop -root"
    frontmost = [l for l in get(cmd).splitlines() if
    "ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
    return frontmost[:2]+"0"+frontmost[2:]
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # create application list to cycle through
    if include_single == False:
    pre = [it[0] for it in windows]
    apps = sorted(list(set([it for it in pre if pre.count(it) > 1])))
    else:
    apps = sorted(list(set([it[0] for it in windows])))
    if len(apps) == 0:
    pass
    else:
    # get the frontmost window as a last itm in the cycle
    front = get_frontmost()
    front_pid = [l.split()[2] for l in get("wmctrl -lp").splitlines() if front in l][0]
    last_infront = get("ps -u "+getpass.getuser()+" | grep "+front_pid).split()[-1]
    # determine next apllication to raise
    if not last_infront in apps or last_infront == apps[-1]:
    arg = apps[0]
    print(arg)
    else:
    arg = apps[apps.index(last_infront)+1]
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0] == arg]
    except (subprocess.CalledProcessError, NameError):
    pass






    Option 3: press key combination + click on launcher icon -or- application window to raise all windows on the current viewport



    This is probably the option that is closest to what is described in the question / comment.



    Let's say I have a messy desktop with three nautilus windows buried under other windows.



    <image>



    To raise all nautilus windows (example shortcut: Alt+1):



    • Press Alt+1, release (!)


    • Within 3 seconds, either:



      click on the application's icon in the launcher



      <image>



      or:



      click on one of the application's windows



      <image>



      result:



      <image>




    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    Then:




    • Press your key combination and within 3 seconds, either:



      • click on the application's icon in the launcher

      • click on one of the application's windows


    The script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import time

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])

    def get_frontmost():
    cmd = "xprop -root"
    frontmost = [l for l in get(cmd).splitlines() if
    "ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
    return frontmost[:2]+"0"+frontmost[2:]

    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # get window data for various purposes
    w_data = get("wmctrl -lpG").splitlines()
    non_windows = sum([[l.split()[0] for l in w_data if it in l]
    for it in ("unity-launcher", "unity-panel", "unity-dash", "Hud")], [])
    # get id of current window
    curr_window = get_frontmost()
    # user gets 3 seconds to pick an application window (or launcher icon)
    t = 0
    while t < 4:
    w_id1 = get_frontmost()
    time.sleep(1)
    w_id2 = get_frontmost()
    if w_id1 == w_id2 or w_id2 in non_windows+[curr_window]:
    t = t+1
    else:
    new_frontmost = w_id2
    break
    # raise
    try:
    pid = [l.split()[2] for l in w_data if new_frontmost in l]
    wl_data = [l.split() for l in w_data]
    raise_windows = [l[0] for l in wl_data if pid[0] == l[2] and
    0 < int(l[3]) < res[0] and 0 < int(l[4]) < res[1]]
    [execute("wmctrl -ia "+item) for item in raise_windows]
    except NameError:
    pass





    Option 4: a key combination calls an option list, showing the number of windows per application on the current viewport



    This one turned out to be more convenient then I assumed:



    Pressing the (again example-) key combination Alt+1 calls a zenity window, listing all applications and the number of their windows on the current viewport:



    enter image description here



    Simply pressing the or arrows will bring you to the right option. Press Enter and all windows of the chosen application are raised.



    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    The script



    #!/usr/bin/env python3
    import subprocess
    import getpass

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # preparing zenity optionlist
    apps = [item[0] for item in windows]
    # prevent multiple zenity windows
    if apps.count("zenity") > 1:
    pass
    elif apps.count("zenity") > 0:
    execute('zenity --info --text "Another Zenity window is open already"')
    # preventing empty windowlist
    elif len(apps) > 0:
    applist = [[app, str(apps.count(app))] for app in set(apps)]
    applist.sort(key=lambda x: x[1])
    # calling zenity window
    try:
    arg = get('zenity --list --text "Choose an application" '+
    '--title "Current windows" '+
    '--column "application" '+
    '--column "windows" '+
    '--height 250 '+
    '--width 250 '+
    (" ").join(sum(applist, [])))
    except subprocess.CalledProcessError:
    pass
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1])
    for item in windows if arg.startswith(item[0])]
    except (subprocess.CalledProcessError, NameError):
    pass
    else:
    execute('zenity --info --text "No windows to list"')






    Option 5: raise windows of running applications from a launcher icon



    This option exists of a launcher icon, with the currently running applications in a quicklist. Choose one, and all windows of the applications will be raised.



    enter image description here



    The launcher is automatically updated when the list of running applications (on the current viewport) changes. The quicklist shows a different list on other viewports, where windows of other applications are opened (will take 1-2 seconds to adapt).





    As mentioned, although fully functional, this option is a meant as a concept. It has a few minor cosmetic downsides as it is. The most important:



    • The cursor "wheel" keeps spinning for a few seconds after an action. Although it does not effect the functionality, it is a cosmetic downside.

    • It takes 1-2 seconds for the applicationlist in the launcher icon to be updated after the list of running applications changes.

    Furthermore the setup is slightly more complicated (although explained in detail below):



    How to use



    Below you will find:



    two scripts / an icon / a .desktop file



    1. Prepare the setup as in "How to use", save the first (main-) script as raise_app in ~/bin


    2. Save the icon below (right-click, save as) as raise.png



      <icon>




    3. Copy the .desktop file into an empty file, edit the line



       Icon=/path/to/raise.png


      to the real path to the icon (paths with spaces between quotes)

      Save it as raise.desktop in ~/.local/share/applications



    4. Drag the .desktop file to the launcher to add it


    5. copy the second script, paste it into an empty file, save it as update_apps in ~/bin, make it executable.


    6. Add the following command to your startup applications (Dash > Startup Applications > Add):



      update_apps


    7. Log out and back in to make it work.

    The first script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import sys

    arg = sys.argv[1]

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
    except (subprocess.CalledProcessError, NameError):
    pass


    The second script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import time
    import os

    dtfile = os.environ["HOME"]+"/.local/share/applications/raise.desktop"

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    def applist():
    try:
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    except subprocess.CalledProcessError:
    return []
    else:
    return set([app[0] for app in windows])

    def update_dtfile(applications, text):
    actionline = "Actions="+(";").join(applications)+";n"
    with open(dtfile) as src:
    lines = src.readlines()
    lines = lines[:[i for i in range(len(lines))
    if lines[i].startswith("Actions=")][0]]+[actionline]
    for item in text:
    for it in item:
    lines.append(it)
    with open(dtfile, "wt") as out:
    for line in lines:
    out.write(line)

    while True:
    apps1 = applist()
    time.sleep(1)
    apps2 = applist()
    if apps1 != apps2:
    text = [["[Desktop Action "+it+"]n", "Name="+it+"n",
    "Exec=raise_app "+it+"n", "OnlyShowIn=Unity;nn",
    ]for it in apps2]
    update_dtfile(apps2, text)


    The .desktop file



    [Desktop Entry]
    Name=Raise application windows
    Comment=Raise groups of windows
    Icon=/path/to/raise.png
    Terminal=false
    Type=Application
    Version=1.0

    Actions=






    Brief Explanation



    All solutions above use wmctrl to create a window list, using the wmctrl -lpG command. This command produces lines, looking like:



    0x044000b3 0 3429 65 24 1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox


    These lines include:



    • 1st column: the window's id (that we can use to raise it)

    • 3rd column: the pid that owns the window.

    • 4th / 5th column: the window's geometry x-y (that we use to see if the window is on the current viewport, i.c.w xrandr)

    The pid is looked up in the output of ps -u <username> to get a "user-readable" identification (name) of the application.

    Thus we can allocate windows to applications. Subsequently we can raise the windows of a given application in a for loop with the command wmctrl -ia.



    In option 3

    the script starts a 3- second "waiting" loop, using the xprop -root command repeatedly to see if there is any change in what is the frontmost window; this will happen if the user either clicks on a launcher icon to raise an application's window, or clicks on a window directly. If so, the while- loop breaks and looks up the "new" frontmost application, and subsequently raises all other windows of that application.






    share|improve this answer

























    • I agree, and thanks again for all your effort! :) || There's a weird thing that I didn't notice before. Sometimes after using the Option 2 script, when an application window is focused (that is not maximized) and I click on another window that is visible "below", the application below below doesn't get the focus.

      – Joschua
      Jan 8 '15 at 22:47











    • @Joschua the OP of this question: askubuntu.com/questions/575830/… attended me of a bug that was introduced at the latest "feature" update. True/False were mixed up, causing the script to crash when no applications have more then one window. If you use option2, please update to the latest version.

      – Jacob Vlijm
      Jan 21 '15 at 19:22











    • Option 1 not working for me on ubuntu xenial. something@something:~/bin$ ./raise_app Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged. I was trying to open terminal windows. Nothing happened.

      – xtrinch
      Sep 17 '16 at 12:33











    • @Nirri what application name did you use? The message is quite normal if a zenity window runs without a Gtk parent. "Discouraged" is not an error.

      – Jacob Vlijm
      Sep 17 '16 at 12:39












    • First chars of terminal. It works - kind of - it raises a window of any app - but only one of them, not all of them as expected @user72216

      – xtrinch
      Sep 17 '16 at 12:42















    21





    +50









    EDIT -new answer-



    The answer(s) below is/are still totally valid, and so the suggested options. Ongoing insight however made me add this option to use the indicator below, which is probably the most elegant solution.



    As such, it should probably replace option 5 (using a .desktop file).



    Simply choose the application from the list, and all windows of the corresponding application (present on the current viewport) will raise:



    enter image description here



    How to use



    from ppa:



    sudo add-apt-repository ppa:vlijm/upfront
    sudo apt-get update
    sudo apt-get install upfront


    ...or manually:



    #!/usr/bin/env python3
    import signal
    import gi
    gi.require_version('Gtk', '3.0')
    gi.require_version('AppIndicator3', '0.1')
    from gi.repository import Gtk, AppIndicator3, GObject
    import time
    from threading import Thread
    import os
    import subprocess
    import getpass

    currpath = os.path.dirname(os.path.realpath(__file__))

    class Indicator():
    def __init__(self):
    self.app = 'raise_apps'
    iconpath = os.path.join(currpath, "raise.png")
    self.indicator = AppIndicator3.Indicator.new(
    self.app, iconpath,
    AppIndicator3.IndicatorCategory.OTHER)
    self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
    self.indicator.set_menu(self.create_menu())
    # the thread:
    self.update = Thread(target=self.check_recent)
    # daemonize the thread to make the indicator stopable
    self.update.setDaemon(True)
    self.update.start()

    def create_menu(self):
    # creates the (initial) menu
    self.menu = Gtk.Menu()
    # separator
    initial = Gtk.MenuItem("Fetching list...")
    menu_sep = Gtk.SeparatorMenuItem()
    self.menu.append(initial)
    self.menu.append(menu_sep)
    # item_quit.show()
    self.menu.show_all()
    return self.menu

    def raise_wins(self, *args):
    index = self.menu.get_children().index(self.menu.get_active())
    selection = self.menu_items2[index][1]
    for w in selection:
    execute(["wmctrl", "-ia", w])

    def set_new(self):
    # update the list, appearing in the menu
    for i in self.menu.get_children():
    self.menu.remove(i)
    for app in self.menu_items2:

    sub = Gtk.MenuItem(app[0])
    self.menu.append(sub)
    sub.connect('activate', self.raise_wins)
    # separator
    menu_sep = Gtk.SeparatorMenuItem()
    self.menu.append(menu_sep)
    # quit
    item_quit = Gtk.MenuItem('Quit')
    item_quit.connect('activate', self.stop)
    self.menu.append(item_quit)
    self.menu.show_all()

    def get_apps(self):
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
    # windows on current viewport
    relevant = [w for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # pids
    pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
    matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
    return [m for m in matches if m[1]]

    def check_recent(self):
    self.menu_items1 = []
    while True:
    time.sleep(4)
    self.menu_items2 = self.get_apps()
    for app in self.menu_items2:
    app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
    if self.menu_items2 != self.menu_items1:
    GObject.idle_add(
    self.set_new,
    priority=GObject.PRIORITY_DEFAULT
    )
    self.menu_items1 = self.menu_items2

    def stop(self, source):
    Gtk.main_quit()

    def get(command):
    return subprocess.check_output(command).decode("utf-8")

    def execute(command):
    subprocess.Popen(command)

    Indicator()
    GObject.threads_init()
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    Gtk.main()



    • The indicator needs wmctrl



      sudo apt-get wmctrl


    • Copy the indicator into an empty file, save it as raise_apps.py



    • Copy the image below, save it exactly named raise.png in one and the same directory as the indicator.



      enter image description here




    • Then simply run it by the command:



      python3 /path/to/raise_apps.py




    • Add if you want to Startup Applications:



      /bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py" 



    OLD ANSWER:



    About the question



    With the right tools, it is not very complicated to "just" raise all windows of an application. It is a bit more complicated to make sure only the windows of the current viewport are raised. The real challenge however is to find a convenient way to make the action available to the user.



    Below five options to take care of that, to show how it can be done. All options are ready to be used. The last option however is kind of experimental; it works fine but has a few minor cosmetic downsides, as explained in the description of the option. I added it nevertheless as a concept.



    Spreading the windows automatically in a non- overlapping way, as suggested in a comment, seems not a practical idea to me; if you work in an (application-wise) grouped window setup, the script would possibly unwantedly rearrange windows.



    How to use



    For all options you need to:




    • install wmctrl if it is not yet on your system:



      sudo apt-get install wmctrl



    • create, if it does not exist yet, the directory:



      ~/bin


      (explanation: the directory ~/bin is in $PATH, so you can run executables by their name)



    • Copy the script, corresponding to the option, paste it into an empty file, save it as raise_app (no extension) in ~/bin and make it executable


    In the separate options, possible additional steps will be explained.



    Option 1: choose the application by entering one or more characters



    • Press a key combination, a zenity window will appear

    • Enter one or more characters of the application's name in the entry box

    • Press enter

    This will make all windows of the matching application (on the current viewport) come to front.



    raise all gnome-terminal windows on the current viewport:



    enter image description here





    enter image description here



    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    The script:



    #!/usr/bin/env python3
    import subprocess
    import getpass

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # ask user for first characters
    try:
    arg = get('zenity --entry --text "first characters" --title "application"').strip()
    except subprocess.CalledProcessError:
    pass
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
    except (subprocess.CalledProcessError, NameError):
    pass






    Option 2: cycle through applications and raise their windows with a key combination:



    Let's say I have the script below under a key combination Alt+1. I have several windows open of:



    • firefox

    • gnome-terminal

    • nautilus

    The current state:



    enter image description here



    I press once Alt+1, all nautilus windows are raised:



    <image>



    I press again Alt+1, all firefox windows are raised:



    <image>



    I press again Alt+1, all gnome-terminal windows are raised again, the cycle starts over:



    <image>



    How to use



    • Do the set up as described in "How to use"


    • Add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command



      raise_app


    Then cycle through your applications with grouped application windows with your key combination.



    The script:



    #!/usr/bin/env python3
    import subprocess
    import getpass

    include_single = True # set to False if you only want to cycle through apps with multiple windows

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])

    def get_frontmost():
    cmd = "xprop -root"
    frontmost = [l for l in get(cmd).splitlines() if
    "ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
    return frontmost[:2]+"0"+frontmost[2:]
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # create application list to cycle through
    if include_single == False:
    pre = [it[0] for it in windows]
    apps = sorted(list(set([it for it in pre if pre.count(it) > 1])))
    else:
    apps = sorted(list(set([it[0] for it in windows])))
    if len(apps) == 0:
    pass
    else:
    # get the frontmost window as a last itm in the cycle
    front = get_frontmost()
    front_pid = [l.split()[2] for l in get("wmctrl -lp").splitlines() if front in l][0]
    last_infront = get("ps -u "+getpass.getuser()+" | grep "+front_pid).split()[-1]
    # determine next apllication to raise
    if not last_infront in apps or last_infront == apps[-1]:
    arg = apps[0]
    print(arg)
    else:
    arg = apps[apps.index(last_infront)+1]
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0] == arg]
    except (subprocess.CalledProcessError, NameError):
    pass






    Option 3: press key combination + click on launcher icon -or- application window to raise all windows on the current viewport



    This is probably the option that is closest to what is described in the question / comment.



    Let's say I have a messy desktop with three nautilus windows buried under other windows.



    <image>



    To raise all nautilus windows (example shortcut: Alt+1):



    • Press Alt+1, release (!)


    • Within 3 seconds, either:



      click on the application's icon in the launcher



      <image>



      or:



      click on one of the application's windows



      <image>



      result:



      <image>




    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    Then:




    • Press your key combination and within 3 seconds, either:



      • click on the application's icon in the launcher

      • click on one of the application's windows


    The script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import time

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])

    def get_frontmost():
    cmd = "xprop -root"
    frontmost = [l for l in get(cmd).splitlines() if
    "ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
    return frontmost[:2]+"0"+frontmost[2:]

    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # get window data for various purposes
    w_data = get("wmctrl -lpG").splitlines()
    non_windows = sum([[l.split()[0] for l in w_data if it in l]
    for it in ("unity-launcher", "unity-panel", "unity-dash", "Hud")], [])
    # get id of current window
    curr_window = get_frontmost()
    # user gets 3 seconds to pick an application window (or launcher icon)
    t = 0
    while t < 4:
    w_id1 = get_frontmost()
    time.sleep(1)
    w_id2 = get_frontmost()
    if w_id1 == w_id2 or w_id2 in non_windows+[curr_window]:
    t = t+1
    else:
    new_frontmost = w_id2
    break
    # raise
    try:
    pid = [l.split()[2] for l in w_data if new_frontmost in l]
    wl_data = [l.split() for l in w_data]
    raise_windows = [l[0] for l in wl_data if pid[0] == l[2] and
    0 < int(l[3]) < res[0] and 0 < int(l[4]) < res[1]]
    [execute("wmctrl -ia "+item) for item in raise_windows]
    except NameError:
    pass





    Option 4: a key combination calls an option list, showing the number of windows per application on the current viewport



    This one turned out to be more convenient then I assumed:



    Pressing the (again example-) key combination Alt+1 calls a zenity window, listing all applications and the number of their windows on the current viewport:



    enter image description here



    Simply pressing the or arrows will bring you to the right option. Press Enter and all windows of the chosen application are raised.



    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    The script



    #!/usr/bin/env python3
    import subprocess
    import getpass

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # preparing zenity optionlist
    apps = [item[0] for item in windows]
    # prevent multiple zenity windows
    if apps.count("zenity") > 1:
    pass
    elif apps.count("zenity") > 0:
    execute('zenity --info --text "Another Zenity window is open already"')
    # preventing empty windowlist
    elif len(apps) > 0:
    applist = [[app, str(apps.count(app))] for app in set(apps)]
    applist.sort(key=lambda x: x[1])
    # calling zenity window
    try:
    arg = get('zenity --list --text "Choose an application" '+
    '--title "Current windows" '+
    '--column "application" '+
    '--column "windows" '+
    '--height 250 '+
    '--width 250 '+
    (" ").join(sum(applist, [])))
    except subprocess.CalledProcessError:
    pass
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1])
    for item in windows if arg.startswith(item[0])]
    except (subprocess.CalledProcessError, NameError):
    pass
    else:
    execute('zenity --info --text "No windows to list"')






    Option 5: raise windows of running applications from a launcher icon



    This option exists of a launcher icon, with the currently running applications in a quicklist. Choose one, and all windows of the applications will be raised.



    enter image description here



    The launcher is automatically updated when the list of running applications (on the current viewport) changes. The quicklist shows a different list on other viewports, where windows of other applications are opened (will take 1-2 seconds to adapt).





    As mentioned, although fully functional, this option is a meant as a concept. It has a few minor cosmetic downsides as it is. The most important:



    • The cursor "wheel" keeps spinning for a few seconds after an action. Although it does not effect the functionality, it is a cosmetic downside.

    • It takes 1-2 seconds for the applicationlist in the launcher icon to be updated after the list of running applications changes.

    Furthermore the setup is slightly more complicated (although explained in detail below):



    How to use



    Below you will find:



    two scripts / an icon / a .desktop file



    1. Prepare the setup as in "How to use", save the first (main-) script as raise_app in ~/bin


    2. Save the icon below (right-click, save as) as raise.png



      <icon>




    3. Copy the .desktop file into an empty file, edit the line



       Icon=/path/to/raise.png


      to the real path to the icon (paths with spaces between quotes)

      Save it as raise.desktop in ~/.local/share/applications



    4. Drag the .desktop file to the launcher to add it


    5. copy the second script, paste it into an empty file, save it as update_apps in ~/bin, make it executable.


    6. Add the following command to your startup applications (Dash > Startup Applications > Add):



      update_apps


    7. Log out and back in to make it work.

    The first script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import sys

    arg = sys.argv[1]

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
    except (subprocess.CalledProcessError, NameError):
    pass


    The second script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import time
    import os

    dtfile = os.environ["HOME"]+"/.local/share/applications/raise.desktop"

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    def applist():
    try:
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    except subprocess.CalledProcessError:
    return []
    else:
    return set([app[0] for app in windows])

    def update_dtfile(applications, text):
    actionline = "Actions="+(";").join(applications)+";n"
    with open(dtfile) as src:
    lines = src.readlines()
    lines = lines[:[i for i in range(len(lines))
    if lines[i].startswith("Actions=")][0]]+[actionline]
    for item in text:
    for it in item:
    lines.append(it)
    with open(dtfile, "wt") as out:
    for line in lines:
    out.write(line)

    while True:
    apps1 = applist()
    time.sleep(1)
    apps2 = applist()
    if apps1 != apps2:
    text = [["[Desktop Action "+it+"]n", "Name="+it+"n",
    "Exec=raise_app "+it+"n", "OnlyShowIn=Unity;nn",
    ]for it in apps2]
    update_dtfile(apps2, text)


    The .desktop file



    [Desktop Entry]
    Name=Raise application windows
    Comment=Raise groups of windows
    Icon=/path/to/raise.png
    Terminal=false
    Type=Application
    Version=1.0

    Actions=






    Brief Explanation



    All solutions above use wmctrl to create a window list, using the wmctrl -lpG command. This command produces lines, looking like:



    0x044000b3 0 3429 65 24 1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox


    These lines include:



    • 1st column: the window's id (that we can use to raise it)

    • 3rd column: the pid that owns the window.

    • 4th / 5th column: the window's geometry x-y (that we use to see if the window is on the current viewport, i.c.w xrandr)

    The pid is looked up in the output of ps -u <username> to get a "user-readable" identification (name) of the application.

    Thus we can allocate windows to applications. Subsequently we can raise the windows of a given application in a for loop with the command wmctrl -ia.



    In option 3

    the script starts a 3- second "waiting" loop, using the xprop -root command repeatedly to see if there is any change in what is the frontmost window; this will happen if the user either clicks on a launcher icon to raise an application's window, or clicks on a window directly. If so, the while- loop breaks and looks up the "new" frontmost application, and subsequently raises all other windows of that application.






    share|improve this answer

























    • I agree, and thanks again for all your effort! :) || There's a weird thing that I didn't notice before. Sometimes after using the Option 2 script, when an application window is focused (that is not maximized) and I click on another window that is visible "below", the application below below doesn't get the focus.

      – Joschua
      Jan 8 '15 at 22:47











    • @Joschua the OP of this question: askubuntu.com/questions/575830/… attended me of a bug that was introduced at the latest "feature" update. True/False were mixed up, causing the script to crash when no applications have more then one window. If you use option2, please update to the latest version.

      – Jacob Vlijm
      Jan 21 '15 at 19:22











    • Option 1 not working for me on ubuntu xenial. something@something:~/bin$ ./raise_app Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged. I was trying to open terminal windows. Nothing happened.

      – xtrinch
      Sep 17 '16 at 12:33











    • @Nirri what application name did you use? The message is quite normal if a zenity window runs without a Gtk parent. "Discouraged" is not an error.

      – Jacob Vlijm
      Sep 17 '16 at 12:39












    • First chars of terminal. It works - kind of - it raises a window of any app - but only one of them, not all of them as expected @user72216

      – xtrinch
      Sep 17 '16 at 12:42













    21





    +50







    21





    +50



    21




    +50





    EDIT -new answer-



    The answer(s) below is/are still totally valid, and so the suggested options. Ongoing insight however made me add this option to use the indicator below, which is probably the most elegant solution.



    As such, it should probably replace option 5 (using a .desktop file).



    Simply choose the application from the list, and all windows of the corresponding application (present on the current viewport) will raise:



    enter image description here



    How to use



    from ppa:



    sudo add-apt-repository ppa:vlijm/upfront
    sudo apt-get update
    sudo apt-get install upfront


    ...or manually:



    #!/usr/bin/env python3
    import signal
    import gi
    gi.require_version('Gtk', '3.0')
    gi.require_version('AppIndicator3', '0.1')
    from gi.repository import Gtk, AppIndicator3, GObject
    import time
    from threading import Thread
    import os
    import subprocess
    import getpass

    currpath = os.path.dirname(os.path.realpath(__file__))

    class Indicator():
    def __init__(self):
    self.app = 'raise_apps'
    iconpath = os.path.join(currpath, "raise.png")
    self.indicator = AppIndicator3.Indicator.new(
    self.app, iconpath,
    AppIndicator3.IndicatorCategory.OTHER)
    self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
    self.indicator.set_menu(self.create_menu())
    # the thread:
    self.update = Thread(target=self.check_recent)
    # daemonize the thread to make the indicator stopable
    self.update.setDaemon(True)
    self.update.start()

    def create_menu(self):
    # creates the (initial) menu
    self.menu = Gtk.Menu()
    # separator
    initial = Gtk.MenuItem("Fetching list...")
    menu_sep = Gtk.SeparatorMenuItem()
    self.menu.append(initial)
    self.menu.append(menu_sep)
    # item_quit.show()
    self.menu.show_all()
    return self.menu

    def raise_wins(self, *args):
    index = self.menu.get_children().index(self.menu.get_active())
    selection = self.menu_items2[index][1]
    for w in selection:
    execute(["wmctrl", "-ia", w])

    def set_new(self):
    # update the list, appearing in the menu
    for i in self.menu.get_children():
    self.menu.remove(i)
    for app in self.menu_items2:

    sub = Gtk.MenuItem(app[0])
    self.menu.append(sub)
    sub.connect('activate', self.raise_wins)
    # separator
    menu_sep = Gtk.SeparatorMenuItem()
    self.menu.append(menu_sep)
    # quit
    item_quit = Gtk.MenuItem('Quit')
    item_quit.connect('activate', self.stop)
    self.menu.append(item_quit)
    self.menu.show_all()

    def get_apps(self):
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
    # windows on current viewport
    relevant = [w for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # pids
    pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
    matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
    return [m for m in matches if m[1]]

    def check_recent(self):
    self.menu_items1 = []
    while True:
    time.sleep(4)
    self.menu_items2 = self.get_apps()
    for app in self.menu_items2:
    app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
    if self.menu_items2 != self.menu_items1:
    GObject.idle_add(
    self.set_new,
    priority=GObject.PRIORITY_DEFAULT
    )
    self.menu_items1 = self.menu_items2

    def stop(self, source):
    Gtk.main_quit()

    def get(command):
    return subprocess.check_output(command).decode("utf-8")

    def execute(command):
    subprocess.Popen(command)

    Indicator()
    GObject.threads_init()
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    Gtk.main()



    • The indicator needs wmctrl



      sudo apt-get wmctrl


    • Copy the indicator into an empty file, save it as raise_apps.py



    • Copy the image below, save it exactly named raise.png in one and the same directory as the indicator.



      enter image description here




    • Then simply run it by the command:



      python3 /path/to/raise_apps.py




    • Add if you want to Startup Applications:



      /bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py" 



    OLD ANSWER:



    About the question



    With the right tools, it is not very complicated to "just" raise all windows of an application. It is a bit more complicated to make sure only the windows of the current viewport are raised. The real challenge however is to find a convenient way to make the action available to the user.



    Below five options to take care of that, to show how it can be done. All options are ready to be used. The last option however is kind of experimental; it works fine but has a few minor cosmetic downsides, as explained in the description of the option. I added it nevertheless as a concept.



    Spreading the windows automatically in a non- overlapping way, as suggested in a comment, seems not a practical idea to me; if you work in an (application-wise) grouped window setup, the script would possibly unwantedly rearrange windows.



    How to use



    For all options you need to:




    • install wmctrl if it is not yet on your system:



      sudo apt-get install wmctrl



    • create, if it does not exist yet, the directory:



      ~/bin


      (explanation: the directory ~/bin is in $PATH, so you can run executables by their name)



    • Copy the script, corresponding to the option, paste it into an empty file, save it as raise_app (no extension) in ~/bin and make it executable


    In the separate options, possible additional steps will be explained.



    Option 1: choose the application by entering one or more characters



    • Press a key combination, a zenity window will appear

    • Enter one or more characters of the application's name in the entry box

    • Press enter

    This will make all windows of the matching application (on the current viewport) come to front.



    raise all gnome-terminal windows on the current viewport:



    enter image description here





    enter image description here



    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    The script:



    #!/usr/bin/env python3
    import subprocess
    import getpass

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # ask user for first characters
    try:
    arg = get('zenity --entry --text "first characters" --title "application"').strip()
    except subprocess.CalledProcessError:
    pass
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
    except (subprocess.CalledProcessError, NameError):
    pass






    Option 2: cycle through applications and raise their windows with a key combination:



    Let's say I have the script below under a key combination Alt+1. I have several windows open of:



    • firefox

    • gnome-terminal

    • nautilus

    The current state:



    enter image description here



    I press once Alt+1, all nautilus windows are raised:



    <image>



    I press again Alt+1, all firefox windows are raised:



    <image>



    I press again Alt+1, all gnome-terminal windows are raised again, the cycle starts over:



    <image>



    How to use



    • Do the set up as described in "How to use"


    • Add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command



      raise_app


    Then cycle through your applications with grouped application windows with your key combination.



    The script:



    #!/usr/bin/env python3
    import subprocess
    import getpass

    include_single = True # set to False if you only want to cycle through apps with multiple windows

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])

    def get_frontmost():
    cmd = "xprop -root"
    frontmost = [l for l in get(cmd).splitlines() if
    "ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
    return frontmost[:2]+"0"+frontmost[2:]
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # create application list to cycle through
    if include_single == False:
    pre = [it[0] for it in windows]
    apps = sorted(list(set([it for it in pre if pre.count(it) > 1])))
    else:
    apps = sorted(list(set([it[0] for it in windows])))
    if len(apps) == 0:
    pass
    else:
    # get the frontmost window as a last itm in the cycle
    front = get_frontmost()
    front_pid = [l.split()[2] for l in get("wmctrl -lp").splitlines() if front in l][0]
    last_infront = get("ps -u "+getpass.getuser()+" | grep "+front_pid).split()[-1]
    # determine next apllication to raise
    if not last_infront in apps or last_infront == apps[-1]:
    arg = apps[0]
    print(arg)
    else:
    arg = apps[apps.index(last_infront)+1]
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0] == arg]
    except (subprocess.CalledProcessError, NameError):
    pass






    Option 3: press key combination + click on launcher icon -or- application window to raise all windows on the current viewport



    This is probably the option that is closest to what is described in the question / comment.



    Let's say I have a messy desktop with three nautilus windows buried under other windows.



    <image>



    To raise all nautilus windows (example shortcut: Alt+1):



    • Press Alt+1, release (!)


    • Within 3 seconds, either:



      click on the application's icon in the launcher



      <image>



      or:



      click on one of the application's windows



      <image>



      result:



      <image>




    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    Then:




    • Press your key combination and within 3 seconds, either:



      • click on the application's icon in the launcher

      • click on one of the application's windows


    The script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import time

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])

    def get_frontmost():
    cmd = "xprop -root"
    frontmost = [l for l in get(cmd).splitlines() if
    "ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
    return frontmost[:2]+"0"+frontmost[2:]

    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # get window data for various purposes
    w_data = get("wmctrl -lpG").splitlines()
    non_windows = sum([[l.split()[0] for l in w_data if it in l]
    for it in ("unity-launcher", "unity-panel", "unity-dash", "Hud")], [])
    # get id of current window
    curr_window = get_frontmost()
    # user gets 3 seconds to pick an application window (or launcher icon)
    t = 0
    while t < 4:
    w_id1 = get_frontmost()
    time.sleep(1)
    w_id2 = get_frontmost()
    if w_id1 == w_id2 or w_id2 in non_windows+[curr_window]:
    t = t+1
    else:
    new_frontmost = w_id2
    break
    # raise
    try:
    pid = [l.split()[2] for l in w_data if new_frontmost in l]
    wl_data = [l.split() for l in w_data]
    raise_windows = [l[0] for l in wl_data if pid[0] == l[2] and
    0 < int(l[3]) < res[0] and 0 < int(l[4]) < res[1]]
    [execute("wmctrl -ia "+item) for item in raise_windows]
    except NameError:
    pass





    Option 4: a key combination calls an option list, showing the number of windows per application on the current viewport



    This one turned out to be more convenient then I assumed:



    Pressing the (again example-) key combination Alt+1 calls a zenity window, listing all applications and the number of their windows on the current viewport:



    enter image description here



    Simply pressing the or arrows will bring you to the right option. Press Enter and all windows of the chosen application are raised.



    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    The script



    #!/usr/bin/env python3
    import subprocess
    import getpass

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # preparing zenity optionlist
    apps = [item[0] for item in windows]
    # prevent multiple zenity windows
    if apps.count("zenity") > 1:
    pass
    elif apps.count("zenity") > 0:
    execute('zenity --info --text "Another Zenity window is open already"')
    # preventing empty windowlist
    elif len(apps) > 0:
    applist = [[app, str(apps.count(app))] for app in set(apps)]
    applist.sort(key=lambda x: x[1])
    # calling zenity window
    try:
    arg = get('zenity --list --text "Choose an application" '+
    '--title "Current windows" '+
    '--column "application" '+
    '--column "windows" '+
    '--height 250 '+
    '--width 250 '+
    (" ").join(sum(applist, [])))
    except subprocess.CalledProcessError:
    pass
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1])
    for item in windows if arg.startswith(item[0])]
    except (subprocess.CalledProcessError, NameError):
    pass
    else:
    execute('zenity --info --text "No windows to list"')






    Option 5: raise windows of running applications from a launcher icon



    This option exists of a launcher icon, with the currently running applications in a quicklist. Choose one, and all windows of the applications will be raised.



    enter image description here



    The launcher is automatically updated when the list of running applications (on the current viewport) changes. The quicklist shows a different list on other viewports, where windows of other applications are opened (will take 1-2 seconds to adapt).





    As mentioned, although fully functional, this option is a meant as a concept. It has a few minor cosmetic downsides as it is. The most important:



    • The cursor "wheel" keeps spinning for a few seconds after an action. Although it does not effect the functionality, it is a cosmetic downside.

    • It takes 1-2 seconds for the applicationlist in the launcher icon to be updated after the list of running applications changes.

    Furthermore the setup is slightly more complicated (although explained in detail below):



    How to use



    Below you will find:



    two scripts / an icon / a .desktop file



    1. Prepare the setup as in "How to use", save the first (main-) script as raise_app in ~/bin


    2. Save the icon below (right-click, save as) as raise.png



      <icon>




    3. Copy the .desktop file into an empty file, edit the line



       Icon=/path/to/raise.png


      to the real path to the icon (paths with spaces between quotes)

      Save it as raise.desktop in ~/.local/share/applications



    4. Drag the .desktop file to the launcher to add it


    5. copy the second script, paste it into an empty file, save it as update_apps in ~/bin, make it executable.


    6. Add the following command to your startup applications (Dash > Startup Applications > Add):



      update_apps


    7. Log out and back in to make it work.

    The first script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import sys

    arg = sys.argv[1]

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
    except (subprocess.CalledProcessError, NameError):
    pass


    The second script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import time
    import os

    dtfile = os.environ["HOME"]+"/.local/share/applications/raise.desktop"

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    def applist():
    try:
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    except subprocess.CalledProcessError:
    return []
    else:
    return set([app[0] for app in windows])

    def update_dtfile(applications, text):
    actionline = "Actions="+(";").join(applications)+";n"
    with open(dtfile) as src:
    lines = src.readlines()
    lines = lines[:[i for i in range(len(lines))
    if lines[i].startswith("Actions=")][0]]+[actionline]
    for item in text:
    for it in item:
    lines.append(it)
    with open(dtfile, "wt") as out:
    for line in lines:
    out.write(line)

    while True:
    apps1 = applist()
    time.sleep(1)
    apps2 = applist()
    if apps1 != apps2:
    text = [["[Desktop Action "+it+"]n", "Name="+it+"n",
    "Exec=raise_app "+it+"n", "OnlyShowIn=Unity;nn",
    ]for it in apps2]
    update_dtfile(apps2, text)


    The .desktop file



    [Desktop Entry]
    Name=Raise application windows
    Comment=Raise groups of windows
    Icon=/path/to/raise.png
    Terminal=false
    Type=Application
    Version=1.0

    Actions=






    Brief Explanation



    All solutions above use wmctrl to create a window list, using the wmctrl -lpG command. This command produces lines, looking like:



    0x044000b3 0 3429 65 24 1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox


    These lines include:



    • 1st column: the window's id (that we can use to raise it)

    • 3rd column: the pid that owns the window.

    • 4th / 5th column: the window's geometry x-y (that we use to see if the window is on the current viewport, i.c.w xrandr)

    The pid is looked up in the output of ps -u <username> to get a "user-readable" identification (name) of the application.

    Thus we can allocate windows to applications. Subsequently we can raise the windows of a given application in a for loop with the command wmctrl -ia.



    In option 3

    the script starts a 3- second "waiting" loop, using the xprop -root command repeatedly to see if there is any change in what is the frontmost window; this will happen if the user either clicks on a launcher icon to raise an application's window, or clicks on a window directly. If so, the while- loop breaks and looks up the "new" frontmost application, and subsequently raises all other windows of that application.






    share|improve this answer















    EDIT -new answer-



    The answer(s) below is/are still totally valid, and so the suggested options. Ongoing insight however made me add this option to use the indicator below, which is probably the most elegant solution.



    As such, it should probably replace option 5 (using a .desktop file).



    Simply choose the application from the list, and all windows of the corresponding application (present on the current viewport) will raise:



    enter image description here



    How to use



    from ppa:



    sudo add-apt-repository ppa:vlijm/upfront
    sudo apt-get update
    sudo apt-get install upfront


    ...or manually:



    #!/usr/bin/env python3
    import signal
    import gi
    gi.require_version('Gtk', '3.0')
    gi.require_version('AppIndicator3', '0.1')
    from gi.repository import Gtk, AppIndicator3, GObject
    import time
    from threading import Thread
    import os
    import subprocess
    import getpass

    currpath = os.path.dirname(os.path.realpath(__file__))

    class Indicator():
    def __init__(self):
    self.app = 'raise_apps'
    iconpath = os.path.join(currpath, "raise.png")
    self.indicator = AppIndicator3.Indicator.new(
    self.app, iconpath,
    AppIndicator3.IndicatorCategory.OTHER)
    self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
    self.indicator.set_menu(self.create_menu())
    # the thread:
    self.update = Thread(target=self.check_recent)
    # daemonize the thread to make the indicator stopable
    self.update.setDaemon(True)
    self.update.start()

    def create_menu(self):
    # creates the (initial) menu
    self.menu = Gtk.Menu()
    # separator
    initial = Gtk.MenuItem("Fetching list...")
    menu_sep = Gtk.SeparatorMenuItem()
    self.menu.append(initial)
    self.menu.append(menu_sep)
    # item_quit.show()
    self.menu.show_all()
    return self.menu

    def raise_wins(self, *args):
    index = self.menu.get_children().index(self.menu.get_active())
    selection = self.menu_items2[index][1]
    for w in selection:
    execute(["wmctrl", "-ia", w])

    def set_new(self):
    # update the list, appearing in the menu
    for i in self.menu.get_children():
    self.menu.remove(i)
    for app in self.menu_items2:

    sub = Gtk.MenuItem(app[0])
    self.menu.append(sub)
    sub.connect('activate', self.raise_wins)
    # separator
    menu_sep = Gtk.SeparatorMenuItem()
    self.menu.append(menu_sep)
    # quit
    item_quit = Gtk.MenuItem('Quit')
    item_quit.connect('activate', self.stop)
    self.menu.append(item_quit)
    self.menu.show_all()

    def get_apps(self):
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
    # windows on current viewport
    relevant = [w for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # pids
    pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
    matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
    return [m for m in matches if m[1]]

    def check_recent(self):
    self.menu_items1 = []
    while True:
    time.sleep(4)
    self.menu_items2 = self.get_apps()
    for app in self.menu_items2:
    app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
    if self.menu_items2 != self.menu_items1:
    GObject.idle_add(
    self.set_new,
    priority=GObject.PRIORITY_DEFAULT
    )
    self.menu_items1 = self.menu_items2

    def stop(self, source):
    Gtk.main_quit()

    def get(command):
    return subprocess.check_output(command).decode("utf-8")

    def execute(command):
    subprocess.Popen(command)

    Indicator()
    GObject.threads_init()
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    Gtk.main()



    • The indicator needs wmctrl



      sudo apt-get wmctrl


    • Copy the indicator into an empty file, save it as raise_apps.py



    • Copy the image below, save it exactly named raise.png in one and the same directory as the indicator.



      enter image description here




    • Then simply run it by the command:



      python3 /path/to/raise_apps.py




    • Add if you want to Startup Applications:



      /bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py" 



    OLD ANSWER:



    About the question



    With the right tools, it is not very complicated to "just" raise all windows of an application. It is a bit more complicated to make sure only the windows of the current viewport are raised. The real challenge however is to find a convenient way to make the action available to the user.



    Below five options to take care of that, to show how it can be done. All options are ready to be used. The last option however is kind of experimental; it works fine but has a few minor cosmetic downsides, as explained in the description of the option. I added it nevertheless as a concept.



    Spreading the windows automatically in a non- overlapping way, as suggested in a comment, seems not a practical idea to me; if you work in an (application-wise) grouped window setup, the script would possibly unwantedly rearrange windows.



    How to use



    For all options you need to:




    • install wmctrl if it is not yet on your system:



      sudo apt-get install wmctrl



    • create, if it does not exist yet, the directory:



      ~/bin


      (explanation: the directory ~/bin is in $PATH, so you can run executables by their name)



    • Copy the script, corresponding to the option, paste it into an empty file, save it as raise_app (no extension) in ~/bin and make it executable


    In the separate options, possible additional steps will be explained.



    Option 1: choose the application by entering one or more characters



    • Press a key combination, a zenity window will appear

    • Enter one or more characters of the application's name in the entry box

    • Press enter

    This will make all windows of the matching application (on the current viewport) come to front.



    raise all gnome-terminal windows on the current viewport:



    enter image description here





    enter image description here



    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    The script:



    #!/usr/bin/env python3
    import subprocess
    import getpass

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # ask user for first characters
    try:
    arg = get('zenity --entry --text "first characters" --title "application"').strip()
    except subprocess.CalledProcessError:
    pass
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
    except (subprocess.CalledProcessError, NameError):
    pass






    Option 2: cycle through applications and raise their windows with a key combination:



    Let's say I have the script below under a key combination Alt+1. I have several windows open of:



    • firefox

    • gnome-terminal

    • nautilus

    The current state:



    enter image description here



    I press once Alt+1, all nautilus windows are raised:



    <image>



    I press again Alt+1, all firefox windows are raised:



    <image>



    I press again Alt+1, all gnome-terminal windows are raised again, the cycle starts over:



    <image>



    How to use



    • Do the set up as described in "How to use"


    • Add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command



      raise_app


    Then cycle through your applications with grouped application windows with your key combination.



    The script:



    #!/usr/bin/env python3
    import subprocess
    import getpass

    include_single = True # set to False if you only want to cycle through apps with multiple windows

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])

    def get_frontmost():
    cmd = "xprop -root"
    frontmost = [l for l in get(cmd).splitlines() if
    "ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
    return frontmost[:2]+"0"+frontmost[2:]
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # create application list to cycle through
    if include_single == False:
    pre = [it[0] for it in windows]
    apps = sorted(list(set([it for it in pre if pre.count(it) > 1])))
    else:
    apps = sorted(list(set([it[0] for it in windows])))
    if len(apps) == 0:
    pass
    else:
    # get the frontmost window as a last itm in the cycle
    front = get_frontmost()
    front_pid = [l.split()[2] for l in get("wmctrl -lp").splitlines() if front in l][0]
    last_infront = get("ps -u "+getpass.getuser()+" | grep "+front_pid).split()[-1]
    # determine next apllication to raise
    if not last_infront in apps or last_infront == apps[-1]:
    arg = apps[0]
    print(arg)
    else:
    arg = apps[apps.index(last_infront)+1]
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0] == arg]
    except (subprocess.CalledProcessError, NameError):
    pass






    Option 3: press key combination + click on launcher icon -or- application window to raise all windows on the current viewport



    This is probably the option that is closest to what is described in the question / comment.



    Let's say I have a messy desktop with three nautilus windows buried under other windows.



    <image>



    To raise all nautilus windows (example shortcut: Alt+1):



    • Press Alt+1, release (!)


    • Within 3 seconds, either:



      click on the application's icon in the launcher



      <image>



      or:



      click on one of the application's windows



      <image>



      result:



      <image>




    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    Then:




    • Press your key combination and within 3 seconds, either:



      • click on the application's icon in the launcher

      • click on one of the application's windows


    The script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import time

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])

    def get_frontmost():
    cmd = "xprop -root"
    frontmost = [l for l in get(cmd).splitlines() if
    "ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
    return frontmost[:2]+"0"+frontmost[2:]

    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # get window data for various purposes
    w_data = get("wmctrl -lpG").splitlines()
    non_windows = sum([[l.split()[0] for l in w_data if it in l]
    for it in ("unity-launcher", "unity-panel", "unity-dash", "Hud")], [])
    # get id of current window
    curr_window = get_frontmost()
    # user gets 3 seconds to pick an application window (or launcher icon)
    t = 0
    while t < 4:
    w_id1 = get_frontmost()
    time.sleep(1)
    w_id2 = get_frontmost()
    if w_id1 == w_id2 or w_id2 in non_windows+[curr_window]:
    t = t+1
    else:
    new_frontmost = w_id2
    break
    # raise
    try:
    pid = [l.split()[2] for l in w_data if new_frontmost in l]
    wl_data = [l.split() for l in w_data]
    raise_windows = [l[0] for l in wl_data if pid[0] == l[2] and
    0 < int(l[3]) < res[0] and 0 < int(l[4]) < res[1]]
    [execute("wmctrl -ia "+item) for item in raise_windows]
    except NameError:
    pass





    Option 4: a key combination calls an option list, showing the number of windows per application on the current viewport



    This one turned out to be more convenient then I assumed:



    Pressing the (again example-) key combination Alt+1 calls a zenity window, listing all applications and the number of their windows on the current viewport:



    enter image description here



    Simply pressing the or arrows will bring you to the right option. Press Enter and all windows of the chosen application are raised.



    How to use:



    • Do the set up as described in "How to use"


    • Test-run it by the command:



      raise_app


    • If all works fine, add it to a shortcut key combination of your choice: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command


    The script



    #!/usr/bin/env python3
    import subprocess
    import getpass

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    # preparing zenity optionlist
    apps = [item[0] for item in windows]
    # prevent multiple zenity windows
    if apps.count("zenity") > 1:
    pass
    elif apps.count("zenity") > 0:
    execute('zenity --info --text "Another Zenity window is open already"')
    # preventing empty windowlist
    elif len(apps) > 0:
    applist = [[app, str(apps.count(app))] for app in set(apps)]
    applist.sort(key=lambda x: x[1])
    # calling zenity window
    try:
    arg = get('zenity --list --text "Choose an application" '+
    '--title "Current windows" '+
    '--column "application" '+
    '--column "windows" '+
    '--height 250 '+
    '--width 250 '+
    (" ").join(sum(applist, [])))
    except subprocess.CalledProcessError:
    pass
    # raise matching windows
    try:
    [execute("wmctrl -ia "+item[1])
    for item in windows if arg.startswith(item[0])]
    except (subprocess.CalledProcessError, NameError):
    pass
    else:
    execute('zenity --info --text "No windows to list"')






    Option 5: raise windows of running applications from a launcher icon



    This option exists of a launcher icon, with the currently running applications in a quicklist. Choose one, and all windows of the applications will be raised.



    enter image description here



    The launcher is automatically updated when the list of running applications (on the current viewport) changes. The quicklist shows a different list on other viewports, where windows of other applications are opened (will take 1-2 seconds to adapt).





    As mentioned, although fully functional, this option is a meant as a concept. It has a few minor cosmetic downsides as it is. The most important:



    • The cursor "wheel" keeps spinning for a few seconds after an action. Although it does not effect the functionality, it is a cosmetic downside.

    • It takes 1-2 seconds for the applicationlist in the launcher icon to be updated after the list of running applications changes.

    Furthermore the setup is slightly more complicated (although explained in detail below):



    How to use



    Below you will find:



    two scripts / an icon / a .desktop file



    1. Prepare the setup as in "How to use", save the first (main-) script as raise_app in ~/bin


    2. Save the icon below (right-click, save as) as raise.png



      <icon>




    3. Copy the .desktop file into an empty file, edit the line



       Icon=/path/to/raise.png


      to the real path to the icon (paths with spaces between quotes)

      Save it as raise.desktop in ~/.local/share/applications



    4. Drag the .desktop file to the launcher to add it


    5. copy the second script, paste it into an empty file, save it as update_apps in ~/bin, make it executable.


    6. Add the following command to your startup applications (Dash > Startup Applications > Add):



      update_apps


    7. Log out and back in to make it work.

    The first script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import sys

    arg = sys.argv[1]

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
    except (subprocess.CalledProcessError, NameError):
    pass


    The second script



    #!/usr/bin/env python3
    import subprocess
    import getpass
    import time
    import os

    dtfile = os.environ["HOME"]+"/.local/share/applications/raise.desktop"

    def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

    def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
    # calculate screen resolution
    res_output = get("xrandr").split(); idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    # creating window list on current viewport / id's / application names
    def applist():
    try:
    w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
    windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
    for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    except subprocess.CalledProcessError:
    return []
    else:
    return set([app[0] for app in windows])

    def update_dtfile(applications, text):
    actionline = "Actions="+(";").join(applications)+";n"
    with open(dtfile) as src:
    lines = src.readlines()
    lines = lines[:[i for i in range(len(lines))
    if lines[i].startswith("Actions=")][0]]+[actionline]
    for item in text:
    for it in item:
    lines.append(it)
    with open(dtfile, "wt") as out:
    for line in lines:
    out.write(line)

    while True:
    apps1 = applist()
    time.sleep(1)
    apps2 = applist()
    if apps1 != apps2:
    text = [["[Desktop Action "+it+"]n", "Name="+it+"n",
    "Exec=raise_app "+it+"n", "OnlyShowIn=Unity;nn",
    ]for it in apps2]
    update_dtfile(apps2, text)


    The .desktop file



    [Desktop Entry]
    Name=Raise application windows
    Comment=Raise groups of windows
    Icon=/path/to/raise.png
    Terminal=false
    Type=Application
    Version=1.0

    Actions=






    Brief Explanation



    All solutions above use wmctrl to create a window list, using the wmctrl -lpG command. This command produces lines, looking like:



    0x044000b3 0 3429 65 24 1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox


    These lines include:



    • 1st column: the window's id (that we can use to raise it)

    • 3rd column: the pid that owns the window.

    • 4th / 5th column: the window's geometry x-y (that we use to see if the window is on the current viewport, i.c.w xrandr)

    The pid is looked up in the output of ps -u <username> to get a "user-readable" identification (name) of the application.

    Thus we can allocate windows to applications. Subsequently we can raise the windows of a given application in a for loop with the command wmctrl -ia.



    In option 3

    the script starts a 3- second "waiting" loop, using the xprop -root command repeatedly to see if there is any change in what is the frontmost window; this will happen if the user either clicks on a launcher icon to raise an application's window, or clicks on a window directly. If so, the while- loop breaks and looks up the "new" frontmost application, and subsequently raises all other windows of that application.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 17 '16 at 15:35

























    answered Jan 6 '15 at 9:59









    Jacob VlijmJacob Vlijm

    65.5k9130226




    65.5k9130226












    • I agree, and thanks again for all your effort! :) || There's a weird thing that I didn't notice before. Sometimes after using the Option 2 script, when an application window is focused (that is not maximized) and I click on another window that is visible "below", the application below below doesn't get the focus.

      – Joschua
      Jan 8 '15 at 22:47











    • @Joschua the OP of this question: askubuntu.com/questions/575830/… attended me of a bug that was introduced at the latest "feature" update. True/False were mixed up, causing the script to crash when no applications have more then one window. If you use option2, please update to the latest version.

      – Jacob Vlijm
      Jan 21 '15 at 19:22











    • Option 1 not working for me on ubuntu xenial. something@something:~/bin$ ./raise_app Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged. I was trying to open terminal windows. Nothing happened.

      – xtrinch
      Sep 17 '16 at 12:33











    • @Nirri what application name did you use? The message is quite normal if a zenity window runs without a Gtk parent. "Discouraged" is not an error.

      – Jacob Vlijm
      Sep 17 '16 at 12:39












    • First chars of terminal. It works - kind of - it raises a window of any app - but only one of them, not all of them as expected @user72216

      – xtrinch
      Sep 17 '16 at 12:42

















    • I agree, and thanks again for all your effort! :) || There's a weird thing that I didn't notice before. Sometimes after using the Option 2 script, when an application window is focused (that is not maximized) and I click on another window that is visible "below", the application below below doesn't get the focus.

      – Joschua
      Jan 8 '15 at 22:47











    • @Joschua the OP of this question: askubuntu.com/questions/575830/… attended me of a bug that was introduced at the latest "feature" update. True/False were mixed up, causing the script to crash when no applications have more then one window. If you use option2, please update to the latest version.

      – Jacob Vlijm
      Jan 21 '15 at 19:22











    • Option 1 not working for me on ubuntu xenial. something@something:~/bin$ ./raise_app Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged. I was trying to open terminal windows. Nothing happened.

      – xtrinch
      Sep 17 '16 at 12:33











    • @Nirri what application name did you use? The message is quite normal if a zenity window runs without a Gtk parent. "Discouraged" is not an error.

      – Jacob Vlijm
      Sep 17 '16 at 12:39












    • First chars of terminal. It works - kind of - it raises a window of any app - but only one of them, not all of them as expected @user72216

      – xtrinch
      Sep 17 '16 at 12:42
















    I agree, and thanks again for all your effort! :) || There's a weird thing that I didn't notice before. Sometimes after using the Option 2 script, when an application window is focused (that is not maximized) and I click on another window that is visible "below", the application below below doesn't get the focus.

    – Joschua
    Jan 8 '15 at 22:47





    I agree, and thanks again for all your effort! :) || There's a weird thing that I didn't notice before. Sometimes after using the Option 2 script, when an application window is focused (that is not maximized) and I click on another window that is visible "below", the application below below doesn't get the focus.

    – Joschua
    Jan 8 '15 at 22:47













    @Joschua the OP of this question: askubuntu.com/questions/575830/… attended me of a bug that was introduced at the latest "feature" update. True/False were mixed up, causing the script to crash when no applications have more then one window. If you use option2, please update to the latest version.

    – Jacob Vlijm
    Jan 21 '15 at 19:22





    @Joschua the OP of this question: askubuntu.com/questions/575830/… attended me of a bug that was introduced at the latest "feature" update. True/False were mixed up, causing the script to crash when no applications have more then one window. If you use option2, please update to the latest version.

    – Jacob Vlijm
    Jan 21 '15 at 19:22













    Option 1 not working for me on ubuntu xenial. something@something:~/bin$ ./raise_app Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged. I was trying to open terminal windows. Nothing happened.

    – xtrinch
    Sep 17 '16 at 12:33





    Option 1 not working for me on ubuntu xenial. something@something:~/bin$ ./raise_app Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged. I was trying to open terminal windows. Nothing happened.

    – xtrinch
    Sep 17 '16 at 12:33













    @Nirri what application name did you use? The message is quite normal if a zenity window runs without a Gtk parent. "Discouraged" is not an error.

    – Jacob Vlijm
    Sep 17 '16 at 12:39






    @Nirri what application name did you use? The message is quite normal if a zenity window runs without a Gtk parent. "Discouraged" is not an error.

    – Jacob Vlijm
    Sep 17 '16 at 12:39














    First chars of terminal. It works - kind of - it raises a window of any app - but only one of them, not all of them as expected @user72216

    – xtrinch
    Sep 17 '16 at 12:42





    First chars of terminal. It works - kind of - it raises a window of any app - but only one of them, not all of them as expected @user72216

    – xtrinch
    Sep 17 '16 at 12:42













    1














    There is Super+W shortcut which will show expo of all the currently open windows, though that will include other applications. This comes by default, and doesn't require any changes, so perhaps it's a simplest option available.



    Among other things, you could position windows on right and left halves of the screen with Ctrl+Super+Left/Right buttons, and switch between them with Alt+~ (tilde, the one next to number one key).






    share|improve this answer

























    • That doesn't bring all the windows of an application to the top though. You can see them, but you can't use them without having to click a lot.

      – Joschua
      Jan 8 '15 at 11:49
















    1














    There is Super+W shortcut which will show expo of all the currently open windows, though that will include other applications. This comes by default, and doesn't require any changes, so perhaps it's a simplest option available.



    Among other things, you could position windows on right and left halves of the screen with Ctrl+Super+Left/Right buttons, and switch between them with Alt+~ (tilde, the one next to number one key).






    share|improve this answer

























    • That doesn't bring all the windows of an application to the top though. You can see them, but you can't use them without having to click a lot.

      – Joschua
      Jan 8 '15 at 11:49














    1












    1








    1







    There is Super+W shortcut which will show expo of all the currently open windows, though that will include other applications. This comes by default, and doesn't require any changes, so perhaps it's a simplest option available.



    Among other things, you could position windows on right and left halves of the screen with Ctrl+Super+Left/Right buttons, and switch between them with Alt+~ (tilde, the one next to number one key).






    share|improve this answer















    There is Super+W shortcut which will show expo of all the currently open windows, though that will include other applications. This comes by default, and doesn't require any changes, so perhaps it's a simplest option available.



    Among other things, you could position windows on right and left halves of the screen with Ctrl+Super+Left/Right buttons, and switch between them with Alt+~ (tilde, the one next to number one key).







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 6 '15 at 23:47

























    answered Jan 6 '15 at 23:41









    Sergiy KolodyazhnyySergiy Kolodyazhnyy

    74.5k9155325




    74.5k9155325












    • That doesn't bring all the windows of an application to the top though. You can see them, but you can't use them without having to click a lot.

      – Joschua
      Jan 8 '15 at 11:49


















    • That doesn't bring all the windows of an application to the top though. You can see them, but you can't use them without having to click a lot.

      – Joschua
      Jan 8 '15 at 11:49

















    That doesn't bring all the windows of an application to the top though. You can see them, but you can't use them without having to click a lot.

    – Joschua
    Jan 8 '15 at 11:49






    That doesn't bring all the windows of an application to the top though. You can see them, but you can't use them without having to click a lot.

    – Joschua
    Jan 8 '15 at 11:49












    1














    If you press Alt+Tab to cycle through applications, and you get to one with multiple windows, just keep holding the alt key down and after about 1 full second the icon will be replaced with a view of all of the windows for that application.



    That may or may not be what you're looking for, but it works for me and is a ton simpler, so I figured I'd share the option!






    share|improve this answer


















    • 1





      You can also press the down arrow key to have the application windows show up straight away.

      – Kris
      Aug 2 '16 at 16:12















    1














    If you press Alt+Tab to cycle through applications, and you get to one with multiple windows, just keep holding the alt key down and after about 1 full second the icon will be replaced with a view of all of the windows for that application.



    That may or may not be what you're looking for, but it works for me and is a ton simpler, so I figured I'd share the option!






    share|improve this answer


















    • 1





      You can also press the down arrow key to have the application windows show up straight away.

      – Kris
      Aug 2 '16 at 16:12













    1












    1








    1







    If you press Alt+Tab to cycle through applications, and you get to one with multiple windows, just keep holding the alt key down and after about 1 full second the icon will be replaced with a view of all of the windows for that application.



    That may or may not be what you're looking for, but it works for me and is a ton simpler, so I figured I'd share the option!






    share|improve this answer













    If you press Alt+Tab to cycle through applications, and you get to one with multiple windows, just keep holding the alt key down and after about 1 full second the icon will be replaced with a view of all of the windows for that application.



    That may or may not be what you're looking for, but it works for me and is a ton simpler, so I figured I'd share the option!







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Sep 11 '15 at 0:48









    Sean ColomboSean Colombo

    1113




    1113







    • 1





      You can also press the down arrow key to have the application windows show up straight away.

      – Kris
      Aug 2 '16 at 16:12












    • 1





      You can also press the down arrow key to have the application windows show up straight away.

      – Kris
      Aug 2 '16 at 16:12







    1




    1





    You can also press the down arrow key to have the application windows show up straight away.

    – Kris
    Aug 2 '16 at 16:12





    You can also press the down arrow key to have the application windows show up straight away.

    – Kris
    Aug 2 '16 at 16:12











    0














    I took @JacobVlijm's raise_apps.py script and made some enhancements to it, including making it more robust.



    Specifically, I had found that after a day or two, @JacobVlijm's script would stop working, and I'd have to manually the script, to get it working again. In retrospect, my best guess is that the numerous calls to xrandr eventually cause issues.



    Anyways, I adapted his code, increased the polling frequency from 5 seconds to every 1 second, as it doesn't use much CPU anyways, and made it more robust. I can typically have it running for days/weeks without issues.



    One caveat is that I only call xrandr once during startup, to get screen resolution dimensions. So if you change your screen resolution (e.g. from 1920x1080 to some other resolution), you'll probably want to manually restart raise-apps.py so that it will pick up the new resolution. Personally, I never change my screen resolution, so this is a non-issue for me. Additionally, I have strong reason to believe that too many calls to xrandr were what was causing @JacobVlijm's version of the script to stop working after a day or two, so I would strongly recommend not simply putting the numerous calls to xrandr back in..



    BTW, you need to place the raise.png image in the /usr/local/icons/ directory. Or if you want to put raise.png in a different directory make the appropriate change to the script, so that the script can find the image file.



    Hopefully, Ubuntu will integrate this type of 'raise all windows' functionality into their system sooner than later as it's very useful:



    #!/usr/bin/python2
    #
    # Note to self:
    # You need to add raise.png to /usr/local/icons/ directory.
    #
    # This script was taken from: https://askubuntu.com/questions/446521/how-to-show-raise-all-windows-of-an-application,
    # (@JacobVlijm's answer), and then improved to fix some
    # issues, that were causing it to stop working after a day or two.
    #
    #
    from __future__ import print_function

    from sys import stderr, exit
    import signal
    import gi

    gi.require_version('Gtk', '3.0')
    gi.require_version('AppIndicator3', '0.1')
    from gi.repository import Gtk, AppIndicator3, GObject, GLib

    import logging
    import logging.handlers

    import time
    import os
    import subprocess
    import getpass

    logger = logging.getLogger('MyLogger')
    logger.setLevel(logging.DEBUG)

    log_handler = logging.handlers.SysLogHandler(address='/dev/log')

    logger.addHandler(log_handler)


    currpath = os.path.dirname(os.path.realpath(__file__))

    class Indicator():
    def __init__(self):
    self.app = 'raise-apps'
    iconpath = '/usr/local/icons/raise.png'
    self.indicator = AppIndicator3.Indicator.new(
    self.app, iconpath,
    AppIndicator3.IndicatorCategory.OTHER)
    self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)

    self.prev_menu_item_names = []
    self.menu_items = []

    res_output = get("xrandr").split()
    if (len(res_output) == 0):
    logger.error("raise-apps.py: invocation of xrandr failed! Unable to continue..")
    exit(-1)

    idf = res_output.index("current")
    res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
    (self.screen_width, self.screen_height) = res
    logger.info("raise-apps.py: screen resolution is %s x %s" % (self.screen_width, self.screen_height))

    self.indicator.set_menu(self.create_menu())

    GLib.timeout_add_seconds(1.0, self.check_recent)

    def create_menu(self):
    # creates the (initial) menu
    self.menu = Gtk.Menu()
    # separator
    initial = Gtk.MenuItem("Fetching list...")
    menu_sep = Gtk.SeparatorMenuItem()
    self.menu.append(initial)
    self.menu.append(menu_sep)

    self.menu.show_all()
    return self.menu

    def raise_wins(self, *args):
    index = self.menu.get_children().index(self.menu.get_active())
    selection = self.menu_items[index][1]
    for w in selection:
    execute(["wmctrl", "-ia", w])

    def set_new(self):
    # update the list, appearing in the menu
    for i in self.menu.get_children():
    self.menu.remove(i)
    for app in self.menu_items:

    sub = Gtk.MenuItem(app[0])
    self.menu.append(sub)
    sub.connect('activate', self.raise_wins)
    # separator
    menu_sep = Gtk.SeparatorMenuItem()
    self.menu.append(menu_sep)

    # quit
    item_quit = Gtk.MenuItem('Quit')
    item_quit.connect('activate', self.stop)
    self.menu.append(item_quit)
    self.menu.show_all()

    def get_apps(self):
    # creating window list on current viewport / id's / application names
    w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
    # windows on current viewport
    relevant = [w for w in w_data if 0 < int(w[3]) < self.screen_width and 0 < int(w[4]) < self.screen_height]
    # pids
    pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
    matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
    return [m for m in matches if m[1]]

    def check_recent(self):
    # print("in check_recent()", file=stderr)
    self.menu_items = self.get_apps()
    for app in self.menu_items:
    app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
    # check if menu items have changed:
    has_changed = len(self.menu_items) != len(self.prev_menu_item_names)
    if (not has_changed):
    for i in range(len(self.menu_items)):
    if self.prev_menu_item_names[i] != self.menu_items[i][0]:
    has_changed = True
    break

    if has_changed:
    GObject.idle_add(
    self.set_new,
    priority=GObject.PRIORITY_DEFAULT)

    self.prev_menu_item_names = []
    for item in self.menu_items:
    self.prev_menu_item_names.append(item[0])

    GLib.timeout_add_seconds(1.0, self.check_recent)


    def stop(self, source):
    Gtk.main_quit()


    def recreate_menu(self, *args):
    logger.info("in recreate_menu()")
    self.prev_menu_item_names = []
    self.menu_items = []

    self.menu_items = self.get_apps()
    for app in self.menu_items:
    app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]

    GObject.idle_add(
    self.set_new,
    priority=GObject.PRIORITY_DEFAULT)

    self.prev_menu_item_names = []
    for item in self.menu_items:
    self.prev_menu_item_names.append(item[0])


    def get(command):
    # enable to get a feel for what this app is doing..
    # print("get", command, file=stderr)
    try:
    return subprocess.check_output(command).decode("utf-8")

    except subprocess.CalledProcessError as e:
    logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
    return ""

    except OSError as e:
    logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
    return ""

    def execute(command):
    # enable to get a feel for what this app is doing..
    # print("exec", command, file=stderr)
    try:
    subprocess.call(command)

    except subprocess.CalledProcessError as e:
    logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
    return ""
    except OSError as e:
    logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
    return ""


    logger.info("(raise-apps.py is starting up..)")
    Indicator()
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    Gtk.main()





    share|improve this answer



























      0














      I took @JacobVlijm's raise_apps.py script and made some enhancements to it, including making it more robust.



      Specifically, I had found that after a day or two, @JacobVlijm's script would stop working, and I'd have to manually the script, to get it working again. In retrospect, my best guess is that the numerous calls to xrandr eventually cause issues.



      Anyways, I adapted his code, increased the polling frequency from 5 seconds to every 1 second, as it doesn't use much CPU anyways, and made it more robust. I can typically have it running for days/weeks without issues.



      One caveat is that I only call xrandr once during startup, to get screen resolution dimensions. So if you change your screen resolution (e.g. from 1920x1080 to some other resolution), you'll probably want to manually restart raise-apps.py so that it will pick up the new resolution. Personally, I never change my screen resolution, so this is a non-issue for me. Additionally, I have strong reason to believe that too many calls to xrandr were what was causing @JacobVlijm's version of the script to stop working after a day or two, so I would strongly recommend not simply putting the numerous calls to xrandr back in..



      BTW, you need to place the raise.png image in the /usr/local/icons/ directory. Or if you want to put raise.png in a different directory make the appropriate change to the script, so that the script can find the image file.



      Hopefully, Ubuntu will integrate this type of 'raise all windows' functionality into their system sooner than later as it's very useful:



      #!/usr/bin/python2
      #
      # Note to self:
      # You need to add raise.png to /usr/local/icons/ directory.
      #
      # This script was taken from: https://askubuntu.com/questions/446521/how-to-show-raise-all-windows-of-an-application,
      # (@JacobVlijm's answer), and then improved to fix some
      # issues, that were causing it to stop working after a day or two.
      #
      #
      from __future__ import print_function

      from sys import stderr, exit
      import signal
      import gi

      gi.require_version('Gtk', '3.0')
      gi.require_version('AppIndicator3', '0.1')
      from gi.repository import Gtk, AppIndicator3, GObject, GLib

      import logging
      import logging.handlers

      import time
      import os
      import subprocess
      import getpass

      logger = logging.getLogger('MyLogger')
      logger.setLevel(logging.DEBUG)

      log_handler = logging.handlers.SysLogHandler(address='/dev/log')

      logger.addHandler(log_handler)


      currpath = os.path.dirname(os.path.realpath(__file__))

      class Indicator():
      def __init__(self):
      self.app = 'raise-apps'
      iconpath = '/usr/local/icons/raise.png'
      self.indicator = AppIndicator3.Indicator.new(
      self.app, iconpath,
      AppIndicator3.IndicatorCategory.OTHER)
      self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)

      self.prev_menu_item_names = []
      self.menu_items = []

      res_output = get("xrandr").split()
      if (len(res_output) == 0):
      logger.error("raise-apps.py: invocation of xrandr failed! Unable to continue..")
      exit(-1)

      idf = res_output.index("current")
      res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
      (self.screen_width, self.screen_height) = res
      logger.info("raise-apps.py: screen resolution is %s x %s" % (self.screen_width, self.screen_height))

      self.indicator.set_menu(self.create_menu())

      GLib.timeout_add_seconds(1.0, self.check_recent)

      def create_menu(self):
      # creates the (initial) menu
      self.menu = Gtk.Menu()
      # separator
      initial = Gtk.MenuItem("Fetching list...")
      menu_sep = Gtk.SeparatorMenuItem()
      self.menu.append(initial)
      self.menu.append(menu_sep)

      self.menu.show_all()
      return self.menu

      def raise_wins(self, *args):
      index = self.menu.get_children().index(self.menu.get_active())
      selection = self.menu_items[index][1]
      for w in selection:
      execute(["wmctrl", "-ia", w])

      def set_new(self):
      # update the list, appearing in the menu
      for i in self.menu.get_children():
      self.menu.remove(i)
      for app in self.menu_items:

      sub = Gtk.MenuItem(app[0])
      self.menu.append(sub)
      sub.connect('activate', self.raise_wins)
      # separator
      menu_sep = Gtk.SeparatorMenuItem()
      self.menu.append(menu_sep)

      # quit
      item_quit = Gtk.MenuItem('Quit')
      item_quit.connect('activate', self.stop)
      self.menu.append(item_quit)
      self.menu.show_all()

      def get_apps(self):
      # creating window list on current viewport / id's / application names
      w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
      # windows on current viewport
      relevant = [w for w in w_data if 0 < int(w[3]) < self.screen_width and 0 < int(w[4]) < self.screen_height]
      # pids
      pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
      matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
      return [m for m in matches if m[1]]

      def check_recent(self):
      # print("in check_recent()", file=stderr)
      self.menu_items = self.get_apps()
      for app in self.menu_items:
      app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
      # check if menu items have changed:
      has_changed = len(self.menu_items) != len(self.prev_menu_item_names)
      if (not has_changed):
      for i in range(len(self.menu_items)):
      if self.prev_menu_item_names[i] != self.menu_items[i][0]:
      has_changed = True
      break

      if has_changed:
      GObject.idle_add(
      self.set_new,
      priority=GObject.PRIORITY_DEFAULT)

      self.prev_menu_item_names = []
      for item in self.menu_items:
      self.prev_menu_item_names.append(item[0])

      GLib.timeout_add_seconds(1.0, self.check_recent)


      def stop(self, source):
      Gtk.main_quit()


      def recreate_menu(self, *args):
      logger.info("in recreate_menu()")
      self.prev_menu_item_names = []
      self.menu_items = []

      self.menu_items = self.get_apps()
      for app in self.menu_items:
      app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]

      GObject.idle_add(
      self.set_new,
      priority=GObject.PRIORITY_DEFAULT)

      self.prev_menu_item_names = []
      for item in self.menu_items:
      self.prev_menu_item_names.append(item[0])


      def get(command):
      # enable to get a feel for what this app is doing..
      # print("get", command, file=stderr)
      try:
      return subprocess.check_output(command).decode("utf-8")

      except subprocess.CalledProcessError as e:
      logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
      return ""

      except OSError as e:
      logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
      return ""

      def execute(command):
      # enable to get a feel for what this app is doing..
      # print("exec", command, file=stderr)
      try:
      subprocess.call(command)

      except subprocess.CalledProcessError as e:
      logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
      return ""
      except OSError as e:
      logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
      return ""


      logger.info("(raise-apps.py is starting up..)")
      Indicator()
      signal.signal(signal.SIGINT, signal.SIG_DFL)
      Gtk.main()





      share|improve this answer

























        0












        0








        0







        I took @JacobVlijm's raise_apps.py script and made some enhancements to it, including making it more robust.



        Specifically, I had found that after a day or two, @JacobVlijm's script would stop working, and I'd have to manually the script, to get it working again. In retrospect, my best guess is that the numerous calls to xrandr eventually cause issues.



        Anyways, I adapted his code, increased the polling frequency from 5 seconds to every 1 second, as it doesn't use much CPU anyways, and made it more robust. I can typically have it running for days/weeks without issues.



        One caveat is that I only call xrandr once during startup, to get screen resolution dimensions. So if you change your screen resolution (e.g. from 1920x1080 to some other resolution), you'll probably want to manually restart raise-apps.py so that it will pick up the new resolution. Personally, I never change my screen resolution, so this is a non-issue for me. Additionally, I have strong reason to believe that too many calls to xrandr were what was causing @JacobVlijm's version of the script to stop working after a day or two, so I would strongly recommend not simply putting the numerous calls to xrandr back in..



        BTW, you need to place the raise.png image in the /usr/local/icons/ directory. Or if you want to put raise.png in a different directory make the appropriate change to the script, so that the script can find the image file.



        Hopefully, Ubuntu will integrate this type of 'raise all windows' functionality into their system sooner than later as it's very useful:



        #!/usr/bin/python2
        #
        # Note to self:
        # You need to add raise.png to /usr/local/icons/ directory.
        #
        # This script was taken from: https://askubuntu.com/questions/446521/how-to-show-raise-all-windows-of-an-application,
        # (@JacobVlijm's answer), and then improved to fix some
        # issues, that were causing it to stop working after a day or two.
        #
        #
        from __future__ import print_function

        from sys import stderr, exit
        import signal
        import gi

        gi.require_version('Gtk', '3.0')
        gi.require_version('AppIndicator3', '0.1')
        from gi.repository import Gtk, AppIndicator3, GObject, GLib

        import logging
        import logging.handlers

        import time
        import os
        import subprocess
        import getpass

        logger = logging.getLogger('MyLogger')
        logger.setLevel(logging.DEBUG)

        log_handler = logging.handlers.SysLogHandler(address='/dev/log')

        logger.addHandler(log_handler)


        currpath = os.path.dirname(os.path.realpath(__file__))

        class Indicator():
        def __init__(self):
        self.app = 'raise-apps'
        iconpath = '/usr/local/icons/raise.png'
        self.indicator = AppIndicator3.Indicator.new(
        self.app, iconpath,
        AppIndicator3.IndicatorCategory.OTHER)
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)

        self.prev_menu_item_names = []
        self.menu_items = []

        res_output = get("xrandr").split()
        if (len(res_output) == 0):
        logger.error("raise-apps.py: invocation of xrandr failed! Unable to continue..")
        exit(-1)

        idf = res_output.index("current")
        res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
        (self.screen_width, self.screen_height) = res
        logger.info("raise-apps.py: screen resolution is %s x %s" % (self.screen_width, self.screen_height))

        self.indicator.set_menu(self.create_menu())

        GLib.timeout_add_seconds(1.0, self.check_recent)

        def create_menu(self):
        # creates the (initial) menu
        self.menu = Gtk.Menu()
        # separator
        initial = Gtk.MenuItem("Fetching list...")
        menu_sep = Gtk.SeparatorMenuItem()
        self.menu.append(initial)
        self.menu.append(menu_sep)

        self.menu.show_all()
        return self.menu

        def raise_wins(self, *args):
        index = self.menu.get_children().index(self.menu.get_active())
        selection = self.menu_items[index][1]
        for w in selection:
        execute(["wmctrl", "-ia", w])

        def set_new(self):
        # update the list, appearing in the menu
        for i in self.menu.get_children():
        self.menu.remove(i)
        for app in self.menu_items:

        sub = Gtk.MenuItem(app[0])
        self.menu.append(sub)
        sub.connect('activate', self.raise_wins)
        # separator
        menu_sep = Gtk.SeparatorMenuItem()
        self.menu.append(menu_sep)

        # quit
        item_quit = Gtk.MenuItem('Quit')
        item_quit.connect('activate', self.stop)
        self.menu.append(item_quit)
        self.menu.show_all()

        def get_apps(self):
        # creating window list on current viewport / id's / application names
        w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
        # windows on current viewport
        relevant = [w for w in w_data if 0 < int(w[3]) < self.screen_width and 0 < int(w[4]) < self.screen_height]
        # pids
        pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
        matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
        return [m for m in matches if m[1]]

        def check_recent(self):
        # print("in check_recent()", file=stderr)
        self.menu_items = self.get_apps()
        for app in self.menu_items:
        app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
        # check if menu items have changed:
        has_changed = len(self.menu_items) != len(self.prev_menu_item_names)
        if (not has_changed):
        for i in range(len(self.menu_items)):
        if self.prev_menu_item_names[i] != self.menu_items[i][0]:
        has_changed = True
        break

        if has_changed:
        GObject.idle_add(
        self.set_new,
        priority=GObject.PRIORITY_DEFAULT)

        self.prev_menu_item_names = []
        for item in self.menu_items:
        self.prev_menu_item_names.append(item[0])

        GLib.timeout_add_seconds(1.0, self.check_recent)


        def stop(self, source):
        Gtk.main_quit()


        def recreate_menu(self, *args):
        logger.info("in recreate_menu()")
        self.prev_menu_item_names = []
        self.menu_items = []

        self.menu_items = self.get_apps()
        for app in self.menu_items:
        app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]

        GObject.idle_add(
        self.set_new,
        priority=GObject.PRIORITY_DEFAULT)

        self.prev_menu_item_names = []
        for item in self.menu_items:
        self.prev_menu_item_names.append(item[0])


        def get(command):
        # enable to get a feel for what this app is doing..
        # print("get", command, file=stderr)
        try:
        return subprocess.check_output(command).decode("utf-8")

        except subprocess.CalledProcessError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""

        except OSError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""

        def execute(command):
        # enable to get a feel for what this app is doing..
        # print("exec", command, file=stderr)
        try:
        subprocess.call(command)

        except subprocess.CalledProcessError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""
        except OSError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""


        logger.info("(raise-apps.py is starting up..)")
        Indicator()
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        Gtk.main()





        share|improve this answer













        I took @JacobVlijm's raise_apps.py script and made some enhancements to it, including making it more robust.



        Specifically, I had found that after a day or two, @JacobVlijm's script would stop working, and I'd have to manually the script, to get it working again. In retrospect, my best guess is that the numerous calls to xrandr eventually cause issues.



        Anyways, I adapted his code, increased the polling frequency from 5 seconds to every 1 second, as it doesn't use much CPU anyways, and made it more robust. I can typically have it running for days/weeks without issues.



        One caveat is that I only call xrandr once during startup, to get screen resolution dimensions. So if you change your screen resolution (e.g. from 1920x1080 to some other resolution), you'll probably want to manually restart raise-apps.py so that it will pick up the new resolution. Personally, I never change my screen resolution, so this is a non-issue for me. Additionally, I have strong reason to believe that too many calls to xrandr were what was causing @JacobVlijm's version of the script to stop working after a day or two, so I would strongly recommend not simply putting the numerous calls to xrandr back in..



        BTW, you need to place the raise.png image in the /usr/local/icons/ directory. Or if you want to put raise.png in a different directory make the appropriate change to the script, so that the script can find the image file.



        Hopefully, Ubuntu will integrate this type of 'raise all windows' functionality into their system sooner than later as it's very useful:



        #!/usr/bin/python2
        #
        # Note to self:
        # You need to add raise.png to /usr/local/icons/ directory.
        #
        # This script was taken from: https://askubuntu.com/questions/446521/how-to-show-raise-all-windows-of-an-application,
        # (@JacobVlijm's answer), and then improved to fix some
        # issues, that were causing it to stop working after a day or two.
        #
        #
        from __future__ import print_function

        from sys import stderr, exit
        import signal
        import gi

        gi.require_version('Gtk', '3.0')
        gi.require_version('AppIndicator3', '0.1')
        from gi.repository import Gtk, AppIndicator3, GObject, GLib

        import logging
        import logging.handlers

        import time
        import os
        import subprocess
        import getpass

        logger = logging.getLogger('MyLogger')
        logger.setLevel(logging.DEBUG)

        log_handler = logging.handlers.SysLogHandler(address='/dev/log')

        logger.addHandler(log_handler)


        currpath = os.path.dirname(os.path.realpath(__file__))

        class Indicator():
        def __init__(self):
        self.app = 'raise-apps'
        iconpath = '/usr/local/icons/raise.png'
        self.indicator = AppIndicator3.Indicator.new(
        self.app, iconpath,
        AppIndicator3.IndicatorCategory.OTHER)
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)

        self.prev_menu_item_names = []
        self.menu_items = []

        res_output = get("xrandr").split()
        if (len(res_output) == 0):
        logger.error("raise-apps.py: invocation of xrandr failed! Unable to continue..")
        exit(-1)

        idf = res_output.index("current")
        res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
        (self.screen_width, self.screen_height) = res
        logger.info("raise-apps.py: screen resolution is %s x %s" % (self.screen_width, self.screen_height))

        self.indicator.set_menu(self.create_menu())

        GLib.timeout_add_seconds(1.0, self.check_recent)

        def create_menu(self):
        # creates the (initial) menu
        self.menu = Gtk.Menu()
        # separator
        initial = Gtk.MenuItem("Fetching list...")
        menu_sep = Gtk.SeparatorMenuItem()
        self.menu.append(initial)
        self.menu.append(menu_sep)

        self.menu.show_all()
        return self.menu

        def raise_wins(self, *args):
        index = self.menu.get_children().index(self.menu.get_active())
        selection = self.menu_items[index][1]
        for w in selection:
        execute(["wmctrl", "-ia", w])

        def set_new(self):
        # update the list, appearing in the menu
        for i in self.menu.get_children():
        self.menu.remove(i)
        for app in self.menu_items:

        sub = Gtk.MenuItem(app[0])
        self.menu.append(sub)
        sub.connect('activate', self.raise_wins)
        # separator
        menu_sep = Gtk.SeparatorMenuItem()
        self.menu.append(menu_sep)

        # quit
        item_quit = Gtk.MenuItem('Quit')
        item_quit.connect('activate', self.stop)
        self.menu.append(item_quit)
        self.menu.show_all()

        def get_apps(self):
        # creating window list on current viewport / id's / application names
        w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
        # windows on current viewport
        relevant = [w for w in w_data if 0 < int(w[3]) < self.screen_width and 0 < int(w[4]) < self.screen_height]
        # pids
        pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
        matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
        return [m for m in matches if m[1]]

        def check_recent(self):
        # print("in check_recent()", file=stderr)
        self.menu_items = self.get_apps()
        for app in self.menu_items:
        app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
        # check if menu items have changed:
        has_changed = len(self.menu_items) != len(self.prev_menu_item_names)
        if (not has_changed):
        for i in range(len(self.menu_items)):
        if self.prev_menu_item_names[i] != self.menu_items[i][0]:
        has_changed = True
        break

        if has_changed:
        GObject.idle_add(
        self.set_new,
        priority=GObject.PRIORITY_DEFAULT)

        self.prev_menu_item_names = []
        for item in self.menu_items:
        self.prev_menu_item_names.append(item[0])

        GLib.timeout_add_seconds(1.0, self.check_recent)


        def stop(self, source):
        Gtk.main_quit()


        def recreate_menu(self, *args):
        logger.info("in recreate_menu()")
        self.prev_menu_item_names = []
        self.menu_items = []

        self.menu_items = self.get_apps()
        for app in self.menu_items:
        app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]

        GObject.idle_add(
        self.set_new,
        priority=GObject.PRIORITY_DEFAULT)

        self.prev_menu_item_names = []
        for item in self.menu_items:
        self.prev_menu_item_names.append(item[0])


        def get(command):
        # enable to get a feel for what this app is doing..
        # print("get", command, file=stderr)
        try:
        return subprocess.check_output(command).decode("utf-8")

        except subprocess.CalledProcessError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""

        except OSError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""

        def execute(command):
        # enable to get a feel for what this app is doing..
        # print("exec", command, file=stderr)
        try:
        subprocess.call(command)

        except subprocess.CalledProcessError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""
        except OSError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""


        logger.info("(raise-apps.py is starting up..)")
        Indicator()
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        Gtk.main()






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 1 hour ago









        GinoGino

        1413




        1413



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Ask Ubuntu!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f446521%2fhow-to-show-raise-all-windows-of-an-application%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Möglingen Índice Localización Historia Demografía Referencias Enlaces externos Menú de navegación48°53′18″N 9°07′45″E / 48.888333333333, 9.129166666666748°53′18″N 9°07′45″E / 48.888333333333, 9.1291666666667Sitio web oficial Mapa de Möglingen«Gemeinden in Deutschland nach Fläche, Bevölkerung und Postleitzahl am 30.09.2016»Möglingen

            Virtualbox - Configuration error: Querying “UUID” failed (VERR_CFGM_VALUE_NOT_FOUND)“VERR_SUPLIB_WORLD_WRITABLE” error when trying to installing OS in virtualboxVirtual Box Kernel errorFailed to open a seesion for the virtual machineFailed to open a session for the virtual machineUbuntu 14.04 LTS Virtualbox errorcan't use VM VirtualBoxusing virtualboxI can't run Linux-64 Bit on VirtualBoxUnable to insert the virtual optical disk (VBoxguestaddition) in virtual machine for ubuntu server in win 10VirtuaBox in Ubuntu 18.04 Issues with Win10.ISO Installation

            Antonio De Lisio Carrera Referencias Menú de navegación«Caracas: evolución relacional multipleja»«Cuando los gobiernos subestiman a las localidades: L a Iniciativa para la Integración de la Infraestructura Regional Suramericana (IIRSA) en la frontera Colombo-Venezolana»«Maestría en Planificación Integral del Ambiente»«La Metrópoli Caraqueña: Expansión Simplificadora o Articulación Diversificante»«La Metrópoli Caraqueña: Expansión Simplificadora o Articulación Diversificante»«Conózcanos»«Caracas: evolución relacional multipleja»«La Metrópoli Caraqueña: Expansión Simplificadora o Articulación Diversificante»