¿Cómo llamo a gnome-session-quit con la cuenta regresiva de Unity?

13

Para poder apagar con un atajo de teclado podemos asignar gnome-session-quit ---power-offun atajo personalizado.

En Unity, esto llevará al siguiente diálogo:

ingrese la descripción de la imagen aquí

Luego necesitamos otras al menos dos pulsaciones de teclas para finalmente apagar nuestro sistema. Esto es bastante inconveniente y preferiría el antiguo cuadro de diálogo de apagado cuando podría apagarse simplemente presionando Returno dejando que espere la cuenta regresiva predeterminada de 60 segundos.

Al llamar gnome-session-quit --poweroffdesde una sesión de flashback de sesión de GNOME en el mismo sistema (14.04 LTS), el antiguo cuadro de diálogo que incluye la cuenta regresiva vuelve:

ingrese la descripción de la imagen aquí

Entonces sabemos que habita en alguna parte.

¿Hay alguna forma de llamar a este antiguo cuadro de diálogo cuando se ejecuta una sesión de Unity?

Takkat
fuente
¿La unidad no tiene un temporizador oculto, por lo que se apaga después de 60 segundos de todos modos?
Tim
Para ambos: la cosa con el nuevo diálogo es que aparentemente espera una selección de usuario para saber qué hacer ...: /
Takkat
2
@Serg La ventana pertenece al Administrador de sesión (ejecuté un script de fondo para escribir las propiedades de una nueva ventana en un archivo). El problema es que se comporta de manera diferente, dependiendo del administrador de ventanas.
Jacob Vlijm
1
@JacobVlijm: sí, eso es lo que pude ver también ... aparentemente sondea el WM y luego llama a esta o aquella rutina, pero no he encontrado la manera de forzar esto.
Takkat

Respuestas:

10

Aquí hay un script para emular el comportamiento deseado. Debe ejecutarse como con sudo. Se puede vincular a un atajo de teclado (con la adición preliminar del shutdowncomando al archivo sudoers para permitir la ejecución sin contraseña ). Simplista, conciso, y hace el trabajo.

#!/bin/bash
# Date: June 11,2015
# Author: Serg Kolo
# Description: a script to emulate
# behavior of GNOME session flashback
# shutdown dialog

# Tell ubuntu to shutdown in 1 min
shutdown -P +1 &
# Show the dialog
zenity --question --text="Shutdown now ? Automatic shutdown in 60 seconds" --ok-label="DOIT" 
# If user clicks DOIT, then cancel the old 
# shutdown call that has countdown,
# (because only one shutdown command can be run at a time), and
# tell ubuntu to shutdown immediately
# otherwise - cancel it
if [ $? -eq 0 ];then
        shutdown -c
        shutdown -P now
else
        shutdown -c
fi

Actualización: 14 de junio

Como lo sugiere Takkat, aquí hay un script que utiliza la opción --timer y dbus de zenity para lograr el mismo comportamiento sin necesidad de acceso a sudo:

#!/bin/bash
# Date: June 14,2015
# Author: Serg Kolo
# Description: a script to emulate
# behavior of GNOME session flashback
# shutdown dialog
# version #2

zenity --question --text="Shutdown now ? Autoshutdown in 60 seconds" \
    --cancel-label="DOIT" --ok-label="NOPE" --timeout=60 ||  
  dbus-send --system --print-reply --dest=org.freedesktop.login1 \
    /org/freedesktop/login1 "org.freedesktop.login1.Manager.PowerOff" boolean:true

La idea básica aquí es que la opción de tiempo de espera de zenity sale con un código mayor que 0, lo que generalmente significa que el comando falló. Por lo tanto, al tratar la opción de cancelación y el tiempo de espera de zenity como la condición que permitirá el apagado, usamos el operador OR ( ||) para apagar solo si el usuario hace clic en el botón de cancelación (etiquetado como "DOIT") o el tiempo de espera del diálogo.

Se puede hacer otra variación para mejorar la experiencia del usuario yad(primero debe instalarse con estos comandos sudo apt-add-repository ppa:webupd8team/y-ppa-manager;sudo apt-get update; sudo apg-get install yad). Esta variación utiliza la barra de progreso para que el usuario sepa cuánto tiempo le queda

    #!/bin/bash
    yad --auto-close --sticky --on-top --skip-taskbar --center \
  --text 'Shutdown now ? Autoshutdown in 60 seconds.' \
  --button="gtk-ok:1" --button="gtk-close:0" --image=dialog-question \ 
--title 'Shutdown' --timeout=60 --timeout-indicator=top || 
dbus-send --system --print-reply --dest=org.freedesktop.login1 \
/org/freedesktop/login1 "org.freedesktop.login1.Manager.PowerOff" boolean:true

Otra versión posible, tiene en cuenta que si cambia la etiqueta del botón ok de zenity, el botón resaltado por defecto puede o no ser el botón ok.

zenity --question --timeout 10 --text="Automatic shutdown in 10 seconds"
if [[ $? -eq 1 ]] ; then
    # user clicked Cancel
    exit 
else
    dbus-send --system --print-reply --dest=org.freedesktop.login1 /org/freedesktop/login1 "org.freedesktop.login1.Manager.PowerOff" boolean:true
fi

El script apaga el sistema ante cualquier retorno que no sea 0. Si el script se agota, el valor de retorno de 1 o 5 le dice al script que ejecute la elseparte

Sergiy Kolodyazhnyy
fuente
Funciona de maravilla cuando se ejecuta con sudo o permite que los usuarios no root se apaguen. Prefiero no hacer eso. Permítame sugerirle las siguientes ediciones para permitir que su script sea ejecutado por un usuario mortal: 1. Use dbus para apagar como se sugirió en esta respuesta 2. Use el zenity --timeouttemporizador incorporado. Con esto no tendremos que cancelar / reiniciar el apagado más tarde.
Takkat
@Takkat agregó otro script que usa sus sugerencias. Por favor revise
Sergiy Kolodyazhnyy
De hecho, se apaga sin contraseña de root, pero el botón OK / DOIT no está seleccionado de forma predeterminada para el apagado inmediato con la tecla RETURN. Usamos un script similar con if [[ $? -eq 1 ]] ; then exit \else dbus...condición que hace eso. Obviamente parece que no hay forma de llamar al viejo asistente de cierre de sesión ...
Takkat
Agregue los comandos para instalar yad;)
AB
Ojalá pudiera dividir la recompensa por ambas respuestas. Fue muy difícil decidir aquí después de tener dos respuestas igualmente grandiosas. Finalmente se lo di a Jacob porque su respuesta parece ser un poco más versátil. Pero su script hace su trabajo maravillosamente, y es muy simple. Lo marcaré como aceptado en su lugar para que aparezca como la respuesta principal. Espero que con el tiempo obtenga aún más votos.
Takkat
6

No es literalmente lo que solicitó, pero al menos una solución (efectiva) comparable sería colocar el script a continuación bajo una tecla de acceso directo.

Que hace

Cuando se usa la tecla de acceso directo:

  • el gnome-session-quit --power-offcomando se ejecuta
  • el ratón se mueve al botón correspondiente "cerca", efectivamente hacer preseleccionada en el botón de apagado:

    ingrese la descripción de la imagen aquí

Luego:

  • Si el usuario presiona Enter, el sistema se apaga
  • Si el usuario no hace nada, el sistema espera 30 segundos (o cualquier otro período de tiempo que desee configurar) y se apaga.
  • Si el usuario mueve el mouse durante los 30 segundos, el procedimiento se detiene

La secuencia de comandos

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

#--- set the location of the close button x, y
q_loc = [1050, 525]
#--- set the time to wait before shutdown
countdown = 30

subprocess.Popen(["gnome-session-quit", "--power-off"])
# for slower systems, set a longer break, on faster systems, can be shorter:
time.sleep(0.4)
subprocess.Popen(["xdotool", "mousemove", str(q_loc[0]), str(q_loc[1])])

coords1 = q_loc
t = 0

while True:
    time.sleep(1)
    cmd = "xdotool", "getmouselocation"
    currloc = subprocess.check_output(cmd).decode("utf-8").split()[:2]
    coords2 = [int(n.split(":")[1]) for n in currloc]
    if coords2 != coords1:
        break
    else:
        if t >= countdown:
            subprocess.Popen(["xdotool", "key", "KP_Enter"])
            break
    t += 1

Cómo utilizar

Estoy bastante seguro de que sabes cómo usarlo, pero aquí vamos por razones habituales:

  1. El script usa xdotool

    sudo apt-get install xdotool
    
  2. Copie el script en un archivo vacío, guárdelo como run_close.py

  3. En la sección de cabecera, configure la ubicación de la pantalla del botón de apagado en la ventana de cierre (mi primera suposición fue correcta):

    #--- set the location of the close button x, y
    q_loc = [1050, 525]
    

    y el tiempo de espera antes del apagado desatendido:

    #--- set the time to wait before shutdown
    countdown = 30
    
  4. Pruébalo con el comando:

    python3 /path/to/run_close.py
    

    Pruébelo con todas las opciones: presionar Enterpara apagado inmediato, apagado desatendido y romper el procedimiento con el mouse

  5. Si todo funciona bien, agréguelo a una tecla de acceso directo: elija: Configuración del sistema> "Teclado"> "Accesos directos"> "Accesos directos personalizados". Haga clic en "+" y agregue el comando:

     python3 /path/to/run_close.py
    

EDITAR

Debajo de una versión del script que no necesita ninguna configuración adicional. Calcula las coordenadas del botón Salir, sin importar cuál sea la resolución de la pantalla.

La configuración es prácticamente la misma, pero [3.]se puede omitir.

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

#--- set the time to wait before shutdown
countdown = 30

def get_qloc():
    xr = subprocess.check_output(["xrandr"]).decode("utf-8").split()
    scrs = [s.split("+") for s in xr if all([s.count("x") == 1, s.count("+") == 2])]
    center = [int(int(s)/2) for s in [scr[0] for scr in scrs if scr[1] == "0"][0].split("x")]
    return [center[0] + 250, center[1]]

q_loc = get_qloc()

subprocess.Popen(["gnome-session-quit", "--power-off"])
# for slower systems, set a longer break, on faster systems, can be shorter:
time.sleep(0.4)
subprocess.Popen(["xdotool", "mousemove", str(q_loc[0]), str(q_loc[1])])

coords1 = q_loc
t = 0

while True:
    time.sleep(1)
    cmd = "xdotool", "getmouselocation"
    currloc = subprocess.check_output(cmd).decode("utf-8").split()[:2]
    coords2 = [int(n.split(":")[1]) for n in currloc]
    if coords2 != coords1:
        break
    else:
        if t >= countdown:
            subprocess.Popen(["xdotool", "key", "KP_Enter"])
            break
    t += 1

Explicación

El tamaño de la ventana del Administrador de sesión para cerrar el sistema siempre está centrado y tiene un tamaño fijo (absoluto), independiente de la resolución de la pantalla. Por lo tanto, la posición relativa al centro de la pantalla es un factor constante.

Todo lo que necesitamos hacer es leer la resolución de la pantalla y calcular la posición del botón desde allí.

La función aplicada ( get_qloc()) calcula la resolución de la pantalla izquierda , ya que es donde aparecerá el diálogo.

Nota

El tiempo, establecido en la línea, time.sleep(0.4)está configurado para sistemas relativamente lentos, para asegurarse de que el mouse se mueva después de que aparezca la ventana de apagado. En sistemas más rápidos, puede ser más corto, en sistemas más lentos (como posiblemente una VM) puede ser necesario configurarlo por más tiempo.

Jacob Vlijm
fuente
@Takkat Solucionado, esta versión debería funcionar en cualquier resolución.
Jacob Vlijm
¡Excelente! Funciona perfectamente en mi VM también.
Takkat