Come posso chiamare gnome-session-quit con il conto alla rovescia di Unity?


13

Per poter chiudere con una scorciatoia da tastiera , possiamo assegnare gnome-session-quit ---power-offuna scorciatoia personalizzata.

In Unity questo porterà alla seguente finestra di dialogo:

inserisci qui la descrizione dell'immagine

Quindi abbiamo bisogno di altri almeno due tasti per spegnere finalmente il nostro sistema. Questo è piuttosto scomodo e preferirei la vecchia finestra di spegnimento quando potresti spegnerlo semplicemente premendo Returno lasciandolo attendere il conto alla rovescia predefinito di 60 secondi.

Quando si chiama gnome-session-quit --poweroffda una sessione di flashback della sessione GNOME sullo stesso sistema (14.04 LTS), viene restituita la vecchia finestra di dialogo che include il conto alla rovescia:

inserisci qui la descrizione dell'immagine

Quindi sappiamo che abita da qualche parte.

C'è un modo per chiamare questa vecchia finestra di dialogo quando si esegue una sessione Unity?


L'unità uno non ha un timer nascosto, quindi si spegne comunque dopo 60 secondi ??
Tim

askubuntu.com/questions/14794/… potrebbe essere d'aiuto
Tim

Per entrambi: la cosa con la nuova finestra di dialogo è che apparentemente aspetta una selezione dell'utente per cosa fare ...: /
Takkat

2
@Serg La finestra appartiene a Session Manager (ho eseguito uno script in background per scrivere le proprietà della nuova finestra in un file). Il problema è che si comporta diversamente, a seconda del gestore delle finestre.
Jacob Vlijm,

1
@JacobVlijm: sì, è quello che ho potuto vedere anche io ... sembra che sondi il WM e poi chiama questa o quella routine ma non ho trovato alcun modo per forzarla.
Takkat,

Risposte:


10

Ecco uno script per emulare il comportamento desiderato. Deve essere eseguito come con sudo. Può essere associato a una scorciatoia da tastiera (con preliminare aggiunta del shutdowncomando per file sudoers per consentire run senza password ). Semplicistico, conciso e fa il lavoro.

#!/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

Aggiornamento: 14 giugno

Come suggerito da Takkat, ecco uno script che utilizza l'opzione --timer e dbus di zenity per ottenere lo stesso comportamento senza la necessità di accesso 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

L'idea di base qui è che l'opzione di timeout di zenity termina con un codice maggiore di 0, che in genere significa che il comando non è riuscito. Pertanto, trattando l'opzione di annullamento di zenity e il timeout come condizione che consentirà l'arresto, utilizziamo l'operatore OR ( ||) per arrestare solo se l'utente fa clic sul pulsante Annulla (etichettato come "DOIT") o il timeout della finestra di dialogo.

Un'altra variante per migliorare l'esperienza dell'utente può essere effettuata yad(deve essere installata prima con questi comandi sudo apt-add-repository ppa:webupd8team/y-ppa-manager;sudo apt-get update; sudo apg-get install yad). Questa variazione utilizza la barra di avanzamento per far sapere all'utente quanto tempo è rimasto

    #!/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

Un'altra versione possibile, tiene conto del fatto che se si modifica l'etichetta del pulsante ok di zenity, il pulsante evidenziato per impostazione predefinita potrebbe essere o meno il pulsante 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

Lo script arresta il sistema in caso di ritorno diverso da 0. Se lo script scade, il valore restituito di 1 o 5 indica allo script di eseguire la elseparte


Funziona come un incantesimo quando viene eseguito con sudo o consente agli utenti non root di arrestarsi. Preferirei non farlo. Vorrei suggerire le seguenti modifiche per consentire l'esecuzione dello script da parte di un utente mortale: 1. Utilizzare dbus per lo spegnimento come è stato suggerito in questa risposta 2. Utilizzare il zenity --timeouttimer integrato. In questo modo non dovremo annullare / riavviare l'arresto in un secondo momento.
Takkat,

@Takkat ha aggiunto un altro script che utilizza i tuoi suggerimenti. Per favore, leggi
Sergiy Kolodyazhnyy il

Effettivamente si arresta senza password di root ma il pulsante OK / DOIT non è selezionato per impostazione predefinita per l'arresto immediato con il tasto INVIO. Usiamo uno script simile con if [[ $? -eq 1 ]] ; then exit \else dbus...condizione che lo fa. Ovviamente non sembra esserci modo di chiamare il vecchio aiutante del logout ...
Takkat,

Aggiungi i comandi per installare yad;)
AB

Vorrei poter dividere la generosità per entrambe le risposte. È stato molto difficile decidere qui dopo aver avuto due risposte altrettanto eccellenti. Alla fine l'ho dato a Jacob perché la sua risposta sembra essere un po 'più versatile. Ma la tua sceneggiatura fa il suo lavoro meravigliosamente ed è così semplice. Lo segnerò come accettato invece per farlo apparire come la risposta migliore. Spero che nel tempo otterrà ancora più voti.
Takkat,

6

Non letteralmente quello che hai chiesto, ma almeno una soluzione (effettivamente) comparabile sarebbe quella di mettere lo script sotto sotto un tasto di scelta rapida.

Cosa fa

Quando si utilizza il tasto di scelta rapida:

  • il gnome-session-quit --power-offcomando viene eseguito
  • il mouse viene spostato sul corrispondente pulsante "chiudi", rendendo effettivamente preselezionato il pulsante di spegnimento:

    inserisci qui la descrizione dell'immagine

Poi:

  • Se l'utente preme Enter, il sistema si spegne
  • Se l'utente non fa nulla, il sistema attende per 30 secondi (o qualsiasi altro periodo di tempo che si desidera impostare) e si spegne.
  • Se l'utente sposta il mouse durante i 30 secondi, la procedura viene interrotta

Il copione

#!/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

Come usare

Sono abbastanza sicuro che tu sappia come usarlo, ma qui andiamo per motivi di habbit:

  1. Lo script usa xdotool

    sudo apt-get install xdotool
    
  2. Copia lo script in un file vuoto, salvalo come run_close.py

  3. Nella sezione head, imposta la posizione dello schermo del pulsante di spegnimento nella finestra di chiusura (la mia prima ipotesi era corretta):

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

    e il tempo di attesa prima dell'arresto automatico:

    #--- set the time to wait before shutdown
    countdown = 30
    
  4. Test-eseguirlo con il comando:

    python3 /path/to/run_close.py
    

    Provalo con tutte le opzioni: premendo Enterper lo spegnimento immediato, lo spegnimento automatico e interrompi la procedura con il mouse

  5. Se tutto funziona bene, aggiungilo a un tasto di scelta rapida: scegli: Impostazioni di sistema> "Tastiera"> "Tasti di scelta rapida"> "Tasti di scelta rapida personalizzati". Fai clic su "+" e aggiungi il comando:

     python3 /path/to/run_close.py
    

MODIFICARE

Di seguito una versione dello script che non richiede alcuna impostazione aggiuntiva. Calcola le coordinate del pulsante Esci, indipendentemente dalla risoluzione dello schermo.

L'installazione è praticamente la stessa, ma [3.]può essere saltata.

#!/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

Spiegazione

Le dimensioni della finestra di Session Manager per chiudere il sistema sono sempre centrate e di dimensioni fisse (assolute), indipendentemente dalla risoluzione dello schermo. Pertanto la posizione relativa al centro dello schermo è un fattore costante.

Tutto ciò che dobbiamo fare è leggere la risoluzione dello schermo e calcolare la posizione del pulsante da lì.

La funzione applicata ( get_qloc()) calcola la risoluzione dello schermo sinistro , poiché quella è quella in cui apparirà il dialogo.

Nota

Il tempo impostato nella riga time.sleep(0.4)è impostato per sistemi relativamente lenti, per assicurarsi che il mouse venga spostato dopo la visualizzazione della finestra di spegnimento. Su sistemi più veloci, può essere più breve, su sistemi più lenti (come probabilmente una VM) potrebbe essere necessario impostare su un valore più lungo.


@Takkat Risolto, questa versione dovrebbe funzionare su qualsiasi risoluzione.
Jacob Vlijm,

Grande! Funziona perfettamente anche sulla mia VM.
Takkat,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.