Lo he resuelto con un script en bash que utiliza las siguientes herramientas de XWindows:
- wmctrl
- xwininfo
- xdotool
Lo primero será por tanto instalar estas herramientas en tu sistema Elementary OS:
- sudo apt install wmctrl
- sudo apt install xwininfo
- sudo apt install xdotool
¿Qué hace cada una de ellas?
wmctrl -d: relación de escritorios virtuales

wmctrl -d nos muestra una línea por cada uno de los escritorios virtuales que tenemos. En mi caso tengo 4 escritorios virtuales. Fíjate que marca con un asterisco (*) el que está activo. En la imagen anterior se ve que el escritorio 0 es el que está activo ahora
wmctrl -l: ventanas activas en mi sistema
wmctrl -l nos muestra una línea por cada ventana activa en el sistema.
Veamos campo por campo el sentido de cada línea:
- El primer campo es el ID de la ventana
- El segundo campo es en qué escritorio virtual se encuentra la ventana. Fíjate que -1 es un escritorio no existente.
- El tercer campo es el nombre del PC
- El cuarto campo es el nombre de la ventana.
xwininfo: ¿Está la ventana x minimizada?
Esta herramienta me permite obtener información de detalle de una determinada ventana. Por ejemplo, ¿está minimizada?
Básicamente funciona así: xwininfo -id <idventana>
Donde, idventana es el ID que nos devuelve wmctrl.
xdotool: realizar acciones sobre una ventana
xdotool me permite realizar acciones sobre una ventana concreta:
- maximizar
- minimizar
- restaurar
- asignarle el foco, es decir, pornerla en primer plano y marcarla como activa
Básicamente, lo que hace mi script es:
- Contar el número de ventanas visibles del escritorio actual
- Si n_ventanas_visibles > 0 entonces, minimizar todas
- Si no, restaurar todas las ventanas del escritorio activo
Con un pequeño matiz, cuando minimizo todas, guardo en un fichero temporal cuál es la ventana activa en ese momento. Esto me permitirá que, si vuelvo a restaurar las ventanas, se vuelva a marcar como activa aquella en la que yo estaba trabajando.
A este script yo lo he llamada mDesktop.sh. Para asignarle un atajo de teclado, sencillamente configuro los atajos de teclado personalizados en Elementary OS:
A continuación te muestro el código completo del script:
#!/bin/bash
mute=0
Program=$@
program_workingDir=`dirname $(readlink -f $0)`
status_fname="$program_workingDir/.mdesktop_status"
program_systemWindows="$program_workingDir/.mdesktop_systemWindows"
n_visible=0
window_id=0
window_name=""
window_hidden=0
window_isignorable=0
window_vd=0 #vd means virtual desktop
vd_activeId=0
#-----------------------------------------------------------------------------------------------
function debug() {
if [[ $mute == 0 ]]
then
echo "DEBUG: $1"
fi
}
#-----------------------------------------------------------------------------------------------
function vd_getActiveId() {
local vd_id=-1
local vd_status="-"
while read vDesktop
do
vd_id=`echo "$vDesktop" | tr -s ' ' | cut -f 1 -d " "`
vd_status=`echo "$vDesktop" | tr -s ' ' | cut -f 2 -d " "`
if [ "$vd_status" == "*" ]
then
echo $vd_id
break
fi
done < <(wmctrl -d)
}
#-----------------------------------------------------------------------------------------------
#isSystemWindow:
# All windows in mdestop_systemWindows and also the Desktop
# How to detect the Desktop window?
# Because if you ask xwininfo -id <window_id> -all and you grep Window type: Desktop
# System Windows are marked to vDesktop -1
function isSystemWindow() {
local window_isSystem=0
local window_name=$1
local window_id=$2
local window_isDesktop=0
window_isSystem=$(grep "$window_name" $program_systemWindows | wc -l)
if [[ $window_isSystem == 1 ]]
then
echo $window_isSystem
return
fi
window_isDesktop=$(xwininfo -id $window_id -all | grep "Desktop" | wc -l)
if [[ $window_isDesktop == 1 ]]
then
echo "1"
else
echo "0"
fi
}
#-----------------------------------------------------------------------------------------------
# window_activeId
# Window id which actually is focused, it is, the one which is active
# This value will be saved in .desktop_status so it can be restored
#-----------------------------------------------------------------------------------------------
function windows_minimize_all() {
local window_activeId=-1
debug "windows_minimize_all..."
window_activeId=$(xdotool getactivewindow)
echo "$window_activeId" > $status_fname
while read Window
do
# window_name=`echo "$Window" | tr -s ' ' | cut -f 4 -d " "`
window_id=`echo "$Window" | tr -s ' ' | cut -f 1 -d " "`
window_vd=`echo "$Window" | tr -s ' ' | cut -f 2 -d " "`
if [[ $(isSystemWindow $window_name $window_id) == 1 ]]
then
debug "NOT minimize $window_id: system window"
continue
fi
if [[ $window_vd != $vd_activeId ]]
then
debug "NOT minimize $window_id: in another desktop"
continue
fi
debug "MINIMIZE $window_id"
xdotool windowminimize $window_id
done < <(wmctrl -l)
}
#-----------------------------------------------------------------------------------------------
function windows_restore_all() {
while read Window
do
# window_name=`echo "$Window" | tr -s ' ' | cut -f 4 -d " "`
window_id=`echo "$Window" | tr -s ' ' | cut -f 1 -d " "`
window_vd=`echo "$Window" | tr -s ' ' | cut -f 2 -d " "`
if [[ $(isSystemWindow $window_name $window_id) == 1 ]]
then
debug "NOT RESTORE $window_id: system window"
continue
fi
if [[ $window_vd != $vd_activeId ]]
then
debug "NOT RESTORE $window_id: in another desktop"
continue
fi
xdotool windowactivate $window_id
done < <(wmctrl -l)
# Set focus to the window was active before minimizing all
window_activeId=$(cat $status_fname)
debug "SETTING FOCUS TO: $window_activeId"
xdotool windowactivate $window_activeId
}
#-----------------------------------------------------------------------------------------------
debug "###############################################"
debug "###############################################"
debug "# MAIN ##########################################"
debug "###############################################"
debug "###############################################"
vd_activeId=$(vd_getActiveId)
debug "current virtual desktop=$vd_activeId"
while read Window
do
debug "-----------------------------------------------------------------------"
debug "### 1"
debug "$Window"
window_id=`echo "$Window" | tr -s ' ' | cut -f 1 -d " "`
window_vd=`echo "$Window" | tr -s ' ' | cut -f 2 -d " "`
window_name=`echo "$Window" | tr -s ' ' | cut -f 4 -d " "`
window_hidden=`xwininfo -all -id $window_id | grep "Hidden" | wc -l`
debug "Window Id: $window_id"
debug "Window vd: $window_vd"
debug "Window Hidden: $window_hidden"
debug "Window Name: $window_name"
if [[ $window_vd == "-1" ]]
then
debug "Window virtual desktip is -1, ignore actual window"
continue
fi
window_isignorable=$(isSystemWindow $window_name $window_id)
debug "Window is system: $window_isignorable"
# is current window an ignore Window?
if [[ $window_isignorable == 1 ]]
then
debug "Ignore actual Window"
continue
fi
# is current active virtual desktop?
if [[ $window_vd != $vd_activeId ]]
then
debug "Ignore actual Window: in another desktop"
continue
fi
# Is there any visible window?
if [[ $window_hidden == 0 ]]
then
debug "show_desktop"
let n_visible++
fi
debug "n_visible = $n_visible"
debug "### 4"
done < <(wmctrl -l)
# We must exec every window and minimize or maximize, depending wether it was already minimized or not
debug "###n_visible = $n_visible"
# windows_restore_all
if [[ $n_visible == 0 ]]
then
debug "restore all windows"
windows_restore_all
else
debug "minimize all windows"
windows_minimize_all
fi
|
Fuentes:
- https://unix.stackexchange.com/questions/23565/get-current-virtual-desktop-number-name-tag-id
- https://unix.stackexchange.com/questions/38867/is-it-possible-to-retrieve-the-active-window-process-title-in-gnome
- https://stackoverflow.com/questions/4057078/how-can-you-check-if-a-window-is-minimized-via-the-terminal-in-linux
- https://askubuntu.com/questions/553203/how-to-close-only-one-window-of-an-application
- http://linux.byexamples.com/archives/179/wmctrl-a-handy-tool-for-you-to-manipulate-windows/
- https://askubuntu.com/questions/4876/can-i-minimize-a-window-from-the-command-line
- https://askubuntu.com/questions/703628/how-to-close-minimize-and-maximize-a-specified-window-from-terminal


