I want to close all windows appearing on my desktop. I've thought to do this through pkill, but I could only manage to kill them one at a time, which is not what I want. The end goal is to put this into a script to run a kiosk, it will detect if the kiosk software is running (I figured this part out) and if it is not, then it will kill any windows that are open, and restart my kiosk software.
-
how about restarting gdm or kdmRaza– Raza2014-07-21 18:09:21 +00:00Commented Jul 21, 2014 at 18:09
5 Answers
The simplest approach uses xdotool:
xdotool search "" windowkill %@
xdotool search "" lists every window. windowkill %@ kills every one of them; %@ refers to all the results of the previous search.
You may prefer to use the --maxdepth 1 option to search to limit the windows selected to top-level windows.
-
1Sadly, it does not work when using VNC (xdotool raises a segmentation fault).Diego Queiroz– Diego Queiroz2018-03-30 17:40:05 +00:00Commented Mar 30, 2018 at 17:40
-
That’s probably worth another question - things should be the same under VNC or not.Michael Homer– Michael Homer2018-03-30 17:42:04 +00:00Commented Mar 30, 2018 at 17:42
-
I agree, but it is not. There is a bug report about this issue: github.com/jordansissel/xdotool/issues/126Diego Queiroz– Diego Queiroz2018-03-31 18:18:34 +00:00Commented Mar 31, 2018 at 18:18
this works at least for kde and xfce (gnome not tested, but it might work as well):
1) install wmctrl
2) then create a script called close_windows.sh:
# close all open windows gracefully without closing the Desktop environment
WIN_IDs=$(wmctrl -l | grep -vwE "Desktop$|xfce4-panel$" | cut -f1 -d' ')
for i in $WIN_IDs; do wmctrl -ic "$i"; done
# Keep checking and waiting until all windows are closed (you probably don't need this section)
while test $WIN_IDs; do
sleep 0.1;
WIN_IDs=$(wmctrl -l | grep -vwE "Desktop$|xfce4-panel$" | cut -f1 -d' ')
done
3) make it executable:chmod +x ./close_windows.sh
3) create an entry in the start menu that points to the close_windows script.
4) execute the close_windows script from this entry.
-
Perfect solution. And it also works with VNC. Important to add that you may need to change "Desktop$" to match your installation localization (eg. in Portuguese it is "Área de trabalho$").Diego Queiroz– Diego Queiroz2018-03-30 17:42:17 +00:00Commented Mar 30, 2018 at 17:42
Michael Homer and Guido van Steen have shown ways to kill all windows. This wouldn't kill background processes, if there are any. It wouldn't kill crashed programs whose window has gone but that are still executing without a user interface. So you may prefer to kill the processes instead.
You can run kill -9 -1 as a non-root user to kill all the processes that are running as that user. You would need to run the kiosk application as a dedicated user (that's a standard configuration for kiosks anyway, for security) and to ensure that the kiosk interface restarts when all processes in the session are dead (which is also a standard configuration for kiosks, for robustness).
Guido's answer perfectly works for me. I wrote a small Linux/Windows cross-compilable Pascal prog compiled with Lazarus/FPC for my own use, which launches his wmctrl command, or the equivalent Powershell windows command:
program CloseAll;
{Ferme toutes les fenêtres}
{$mode objfpc}{$H+}
uses
Classes, SysUtils, Process, Crt;
var
p: TProcess;
// i: integer=0;
{$R *.res}
begin
p := TProcess.Create(nil);
try
p.ShowWindow := swoHIDE; // Cache la console
{$ifdef windows}
p.Executable := 'cmd.exe';
p.Parameters.Add('powershell -command "(New-Object -comObject Shell.Application).Windows() | foreach-object {$_.quit()}; Get-Process | Where-Object {$_.MainWindowTitle -ne \"\"} | stop-process"');
{$else}
p.Executable := '/bin/bash';
p.Parameters.Add('-c');
//close all open windows gracefully without closing the Desktop environment
p.Parameters.Add ('WIN_IDs=$(wmctrl -l | grep -vwE "Bureau$|xfce4-panel$" | cut -f1 -d' + #39 + ' ' + #39 + ')' +#10 + 'for i in $WIN_IDs; do wmctrl -ic "$i"; done');
//p.Options := p.Options + [poWaitOnExit, poUsePipes];
{$endif}
p.Execute;
finally
p.Free
end
end.
I also noticed that Diego is right about the desktop name, and my Linux executable would only work on a French xfce environment with the desktop named "Bureau". I was not able to find the desktop name in the environment variables (and it was not worth the trouble).
Perhaps a combination/workaround with a command killall processName and accommodating to the set of possible applications running.
Eg. killing all terminals killall bash, kill all chrome windows killall chrome and that way to close the combination of expected application processes.