4

When I right click on an application's icon in the Unity launcher, I can press Quit to close all the windows corresponding to that application. Is it possible to do the same with a keyboard shortcut which operates on the active window (and all the other windows corresponding to the same application)?

I could do something similar with xkill, but in that case I do not have the message that remembers me of unsaved files.

  • Hi user525864, posted my answer. Please let me know if you manage. – Jacob Vlijm Apr 2 '16 at 15:29
  • Can be done pretty easily for unity and gnome, id say. What are your requirements aside from this being a shortcut capturing the active window and all related to it ? – Sergiy Kolodyazhnyy Apr 2 '16 at 23:26
  • Answer posted , please review – Sergiy Kolodyazhnyy Apr 3 '16 at 1:27
1

The answer by user72216 didn't work always. For example if I opened several Okular (a KDE PDF viewer) windows, the code won't close all windows, as different window ids are assigned to the windows. The following code extracts all window ids and closes them gracefully:

#!/usr/bin/env python3
import subprocess

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

pid = get(["xdotool", "getactivewindow", "getwindowpid"])

# Identify the name of the application
username = get(["users"])
jobs = get(["ps","-u",username])
jobname = ""
for w in jobs.splitlines():
    jobinfo = w.split()
    if pid == jobinfo[0]:
        jobname = jobinfo[-1]
        break

# Get all pids that match the jobname
pidlist = []
for w in jobs.splitlines():
    jobinfo = w.split()
    if jobinfo[-1] == jobname:
        pidlist = pidlist + [jobinfo[0]]

# Close all windows with having the pids
wlist = get(["wmctrl", "-lp"])
for pid in pidlist:
    for w in wlist.splitlines():
        if pid in w and not "Desktop" in w:
            print(w.split()[0])
            subprocess.call(["wmctrl", "-ic", w.split()[0]])
| improve this answer | |
10

How to safely close all windows of a gui application with a shortcut key

The safest way to close an application's window gracefully, and make sure you will not lose data, is using wmctrl (not installed by default):

wmctrl -ic <window_id>

To use it in a script to close all windows of an application:

  1. install both xdotool and wmctrl

    sudo apt-get install wmctrl xdotool
    
  2. Copy the script below into an empty file, save it as stop_active.py

    #!/usr/bin/env python3
    import subprocess
    
    def get(cmd):
        return subprocess.check_output(cmd).decode("utf-8").strip()
    
    pid = get(["xdotool", "getactivewindow", "getwindowpid"])
    for w in get(["wmctrl", "-lp"]).splitlines():
        if pid in w and not "Desktop" in w:
            subprocess.call(["wmctrl", "-ic", w.split()[0]])
    
  3. Add the following command to a shortcut key:

    python3 /path/to/stop_active.py
    

    Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command:

    python3 /path/to/stop_active.py
    

    N.B. don't use ~ or $HOME in a shortcut key, but use absolute paths instead.

Now the shortcut can be used to gracefully close all windows of the frontmost window.

Explanation

I tried the various kill options (kill -2, kill -HUP, kill -s TERM <pid> etc), which are mentioned in several posts to close an application gracefully. Tested on a gedit window with unsaved changes, all of them closed the window happily however, without any interaction.

wmctrl does ask what to do however, similar to Ctrl+Q.

The script then first finds out the pid of the frontmost window, with the command:

xdotool getactivewindow getwindowpid

subsequently, the list of currently opened windows is called with the command:

wmctrl -lp

From this list, the corresponding windows are picked and closed with the command:

wmctrl -ic <window_id>

Note

If you are closing all nautilus windows, in the line

if pid in w and not "Desktop" in w:

"Desktop" is referring to your Desktop window, which normally should always stay. If you are not using an English version of Ubuntu, replace "Desktop" by the localized name of the Desktop in your language.

| improve this answer | |
  • I need help. I have your code in my home folder. If I type python3 ~/stop_active.py in a terminal all the terminal windows are closed and I also have the message from the active windows about running processes. So the code seems to work. But if I add the same command to a shortcut key, when I press the shortcut key nothing happens. am I missing something? – user525864 Apr 2 '16 at 15:33
  • @user525864 Ah, I should have mentioned: in shortcut keys, ~ doesn't work, you need to use full paths :) – Jacob Vlijm Apr 2 '16 at 15:34
  • tanks. It works. – user525864 Apr 2 '16 at 15:44
  • I have just one question. is it really not possible to achieve it in a simpler way? without wmctrl, I mean the launcher Quit already works. is not possible to reuse it somehow? – user525864 Apr 2 '16 at 15:48
  • @user525864 I see of course what you mean, but the thing is, like in many cases, the option is coded inside the application, in this case: Unity. We then depend on the cli options an application offers. Unity does not have a cli option to close all application windows gracefully, so unfortunately, the existing code is not reusable "from outside". – Jacob Vlijm Apr 2 '16 at 15:51
1

Introduction

The script bellow kills all active windows of the currently active window that user is working in. This is meant to be bound to a shortcut.

The script will show a popup prompting the user to confirm before killing all the windows.

The script uses all the native (pre-installed ) tools, such as qdbus,zenity, and bash.

Obtaining the script

You can either copy the script source here or obtain it from my git repository using instructions bellow

  1. sudo apt-get install git
  2. cd /opt ; sudo git clone https://github.com/SergKolo/sergrep.git
  3. The file will be located in /opt/sergrep/kill_windows_set.sh ; Ensure the file is executable with sudo chmod +x kill_windows_set.sh

Binding the script to shortcut

The relevant information can be found here:

How do I bind .sh files to keyboard combination?

Source

#!/usr/bin/env bash
#
###########################################################
# Author: Serg Kolo , contact: 1047481448@qq.com 
# Date: April 2nd , 2016
# Purpose:  Close all windows of the active application
# Written for: https://askubuntu.com/q/753033/295286
# Tested on: Ubuntu 14.04 LTS
###########################################################
# Copyright: Serg Kolo , 2016
#    
#     Permission to use, copy, modify, and distribute this software is hereby granted
#     without fee, provided that  the copyright notice above and this permission statement
#     appear in all copies.
#
#     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
#     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#     DEALINGS IN THE SOFTWARE.

ARGV0="$0"
ARGC=$#
get_running_apps()
{
  qdbus org.ayatana.bamf /org/ayatana/bamf/matcher org.ayatana.bamf.matcher.RunningApplications
}

list_children()
{
 qdbus org.ayatana.bamf "$1"  org.ayatana.bamf.view.Children
}

get_pid()
{
 qdbus org.ayatana.bamf "$1"  org.ayatana.bamf.window.GetPid
}

main()
{
  local ACTIVE
  local apps_list
  apps_list=( $( get_running_apps | tr '\n' ' ' ) )

  for app in ${apps_list[@]} ; do
      ACTIVE=$(qdbus org.ayatana.bamf $app org.ayatana.bamf.view.IsActive)
      if [ "x$ACTIVE" = "xtrue"   ] ; then
         windows=( $( list_children $app | tr '\n' ' ' ) )
      fi
  done

for window in ${windows[@]} ; do
    PIDS+=( $(get_pid $window) )
done

if zenity --question \
   --text="Do you really want to kill ${#PIDS[@]} windows ?" ; 
   then
   kill ${PIDS[@]}
fi

}
main

Script in Action

enter image description here

| improve this answer | |
  • This has a few major downsides: it blindly asks for confirmation, even if no window has unsaved changes to decide on, and -related- it asks one time for all windows, as shown in the image, while the desired decision might differ per window. Furthermore, possibly only one window might have unsaved changes and be out of sight at the moment you have to decide. Why so complicated to re- invent what existing tools already provide in a better way? – Jacob Vlijm Apr 3 '16 at 3:41
  • @JacobVlijm as far as I know , there's not a lot of tools so far to test whether or not a work has or has not been saved. That's for one. It's up to each appplication to implement this feature when it receives the closing signal. When you close LibreOffice unsaved doc, it asks. When you close a terminal window with less open it may or may not ask - depends on the term. Again, same is for cases when "desired decision might differ per window". – Sergiy Kolodyazhnyy Apr 3 '16 at 4:53
  • As for asking one time - that's the desired effect ! User specifically requested a shortcut to kill all windows of an application. They don't want to have shortcut that will prompt them window after window - they could do it manually if they wanted to, but they want automatic way to killall windows – Sergiy Kolodyazhnyy Apr 3 '16 at 4:55
  • In case of wmctrl it uses C language on the low level to implement calls to X server to "gracefully close window". Of course i can implement call to lsof , but that will take longer time – Sergiy Kolodyazhnyy Apr 3 '16 at 5:21
  • About OP's intention: "when I right click to an application in the launcher I can press Quit to close all the windows corresponding to that application. Is it possible to do the same with a keyboard shortcut..." clearly asks for a solution that only asks for confirmation if necessary, and if necessary, per window. Why would you ask for a confirmation for all windows at once? If you didn't want to close it, you didn't fire the command. The question is about not loosing data if, and only if one or more windows have unsaved changes. Exactly like right-click the icon in the launcher. – Jacob Vlijm Apr 3 '16 at 5:50
-2

You could create a shortcut for xkill.

settings < keyboard < shortcuts < custom shortcuts

Add a custom shortcut, then simply write "xkill" in the command menu and set your own shortcut by pressing the keys you want.

Like you said that doesn't give you a "saved unsaved files" message though.

| improve this answer | |
  • 3
    How can you post an answer of which OP mentioned he didn't want it? – Jacob Vlijm Apr 2 '16 at 14:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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