How can I make a shortcut to close all the windows of the same application?
Solution 1:
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:
-
install both
xdotool
andwmctrl
sudo apt-get install wmctrl xdotool
-
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]])
-
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.
Solution 2:
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]])
Solution 3:
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
sudo apt-get install git
cd /opt ; sudo git clone https://github.com/SergKolo/sergrep.git
- The file will be located in
/opt/sergrep/kill_windows_set.sh
; Ensure the file is executable withsudo 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: [email protected]
# 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