15

To be able to shutdown with a keyboard shortcut we can assign gnome-session-quit ---power-off to a custom shortcut.

In Unity this will lead to the following dialog:

enter image description here

Then we need another at least two keystrokes to finally power off our system. This is rather inconvenient and I would prefer the old shutdown dialog when you could poweroff by just pressing Return or letting it wait the default countdown of 60 seconds.

When calling gnome-session-quit --poweroff from a GNOME session flashback session on the same system (14.04 LTS) the old dialog including the countdown comes back:

enter image description here

So we know it dwells somewhere.

Is there any way to call this old dialog when running a Unity session?

12
  • Does the unity one not have a hidden timer, so it does power off after 60 secs anyway??
    – Tim
    Nov 29, 2014 at 13:52
  • askubuntu.com/questions/14794/… might help
    – Tim
    Nov 29, 2014 at 13:54
  • To both: the thing with the new dialog is, that it apparently waits for a user selection for what to do... :/
    – Takkat
    Nov 29, 2014 at 14:03
  • 2
    @Serg The window belongs to Session Manager (I ran a background script to write new window's properties to a file). The problem is that it behaves differently, depending on the window manager. Jun 11, 2015 at 10:58
  • 1
    @JacobVlijm: yeah that's what I could see too... it apparently polls the WM and then calls this or that routine but I've found no way to force this.
    – Takkat
    Jun 11, 2015 at 11:00

2 Answers 2

11

Here's a script to emulate the desired behavior. Must be ran as with sudo. Can be bound to a keyboard shortcut ( with preliminary addition of the shutdown command to sudoers file to allow passwordless run ). Simplistic, concise, and does the job.

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

Update: June 14

As suggested by Takkat, here's a script that utilizes zenity's --timer option and dbus to achieve the same behavior without need for sudo access:

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

Basic idea here is that zenity's timeout option exits with code greater than 0, which typically means command failed. So by treating zenity's cancel option and timeout as the condition that will allow shutdown, we use the OR operator (|| ) to shutdown only if user clicks the cancel button (labeled as "DOIT" ) or dialog times out.

Another variation to improve user experience can be done with yad (needs to be installed first with these commands sudo apt-add-repository ppa:webupd8team/y-ppa-manager;sudo apt-get update; sudo apt-get install yad ). This variation uses progress bar to let user know how much time is left

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

Another possible version does take into account that if you change Zenity's ok button label, the button highlighted by default may or may not be the ok button.

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

The script shuts down the system upon any return that is not 0. If script times out , the return value of either 1 or 5 tells the script to execute the else part

6
  • Works like a charm when run with sudo or allow non-root users to shutdown. I'd rather not do that. Let me suggest the following edits to enable your script being run by a mortal user: 1. Use dbus for poweroff as was suggested in this answer 2. Use the zenity --timeout inbuilt timer. By this we will not have to cancel/restart the shutdown later.
    – Takkat
    Jun 11, 2015 at 19:02
  • @Takkat added another script that uses your suggestions. Please review Jun 14, 2015 at 19:16
  • It does indeed shutdown without root password but the OK/DOIT button is not selected by default for immediate shutdown with RETURN key. We use a similar script with if [[ $? -eq 1 ]] ; then exit \else dbus... condition which does that. Obviously there appears to be no way to call the old logout-helper...
    – Takkat
    Jun 14, 2015 at 19:50
  • Add the commands to install yad ;)
    – A.B.
    Jun 14, 2015 at 21:22
  • Wish I could split the bounty to both answers. It was very hard to decide here after having two such equally great answers. Finally I gave it to Jacob because his answer appears to be a bit more versatile. But your script does its job wonderfully, and it is so simple. I'll mark it as accepted instead to make it show up as the top answer. I hope it will get even more votes over time by this.
    – Takkat
    Jun 16, 2015 at 20:22
5
+200

Not literally what you asked for, but at least an (effectively) comparable solution would be to put the script below under a shortcut key.

What it does

When the shortcut key is used:

  • the gnome-session-quit --power-off command is run
  • the mouse is moved to the corresponding "close" button, effectively making the shutdown button pre- selected:

    enter image description here

Then:

  • If the user presses Enter, the system shuts down
  • If the user does nothing, the system waits for 30 seconds (or any other period of time you'd like to set) and shuts down.
  • If the user moves the mouse during the 30 seconds, the procedure is stopped

The script

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

How to use

I am pretty sure you know how to use it, but here we go for habbit reasons:

  1. The script uses xdotool

    sudo apt-get install xdotool
    
  2. Copy the script into an empty file, save it as run_close.py

  3. In the head section, set the screen's location of the shut-down button in the close- window (my first guess was right):

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

    and the time to wait before unattended shut down:

    #--- set the time to wait before shutdown
    countdown = 30
    
  4. Test-run it by the command:

    python3 /path/to/run_close.py
    

    Test it with all of the option: pressing Enter for immediate shutdown, unattended shutdown and break the procedure by mouse- move

  5. If all works fine, add it to a shortcut key: choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command:

     python3 /path/to/run_close.py
    

EDIT

Below a version of the script that does not need any additional setting. It calculates the coordinates of the quit button, no matter what is the screen's resolution.

The setup is pretty much the same, but [3.] can be skipped.

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

Explanation

The size of the Session Manager window to close the system is always centred and of a fixed (absolute) size, independent to the screen's resolution. Therefore the position relative to the centre of the screen is a constant factor.

All we need to do then is to read the screen's resolution and calculate the button's position from there.

The applied function ( get_qloc() ) calculates the resolution of the left screen, since that is the one where the dialogue will appear.

Note

The time, set in the line time.sleep(0.4) is set for relatively slow systems, to make sure the mouse is moved after the shut down window appears. On faster systems, it can be shorter, on slower systems (like possibly a VM) it might be needed to set to longer.

2
  • @Takkat Fixed, this version should work on any resolution. Jun 12, 2015 at 5:57
  • Great! It works flawlessly on my VM too.
    – Takkat
    Jun 12, 2015 at 17:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .