如何通过Unity的倒计时调用gnome-session-quit?

为了能够使用键盘快捷键关闭,我们可以将gnome-session-quit ---power-off分配给自定义快捷方式。

在Unity中,这将导致以下对话框:

在此处输入图像描述

然后我们需要另外两次击键才能最终关闭我们的系统。 这是相当不方便的,当你可以通过按下Return或让它等待60秒的默认倒计时来关闭电源时我更喜欢旧的关机对话框。

在同一系统(14.04 LTS)上从GNOME会话闪回会话调用gnome-session-quit --poweroff ,包含倒计时的旧对话框会返回:

在此处输入图像描述

所以我们知道它住在某个地方。

有没有办法在运行Unity会话时调用这个旧对话框?

这是一个模拟所需行为的脚本。 必须像sudo 。 可以绑定到键盘快捷键(初步添加shutdown命令到sudoers文件以允许无密码运行 )。 简单,简洁,完成工作。

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

更新:6月14日

正如Takkat所建议的,这是一个利用zenity的–timer选项和dbus来实现相同行为而不需要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 

这里的基本思想是zenity的超时选项以大于0的代码退出,这通常意味着命令失败。 因此,通过将zenity的取消选项和超时视为允许关闭的条件,我们使用OR运算符( || )仅在用户单击取消按钮(标记为“DOIT”)或对话超时时关闭。

另一种改善用户体验的变体可以用yad完成(需要先用这些命令安装sudo apt-add-repository ppa:webupd8team/y-ppa-manager;sudo apt-get update; sudo apg-get install yad )。 此变体使用进度条让用户知道剩余多少时间

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

另一个可能的版本,考虑到如果你改变zenity的ok按钮标签,默认突出显示的按钮可能是也可能不是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 

该脚本在任何非0返回时关闭系统。如果脚本超时,则返回值1或5告诉脚本执行else部分

不是字面上你要求的,但至少一个(有效)可比的解决方案是将下面的脚本放在快捷键下。

它能做什么

使用快捷键时:

  • 执行gnome-session-quit --power-off命令
  • 鼠标移动到相应的“关闭”按钮, 有效地使关闭按钮被预选:

    在此处输入图像描述

然后:

  • 如果用户按Enter键 ,系统将关闭
  • 如果用户什么都不做,系统将等待30秒(或您想要设置的任何其他时间段)并关闭。
  • 如果用户在30秒内移动鼠标,则程序停止

剧本

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

如何使用

我很确定你知道如何使用它,但在这里我们采取habbit理由:

  1. 该脚本使用xdotool

     sudo apt-get install xdotool 
  2. 将脚本复制到空文件中,将其另存为run_close.py

  3. 在head部分,在关闭窗口中设置关闭按钮的屏幕位置(我的第一个猜测是正确的):

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

    以及无人值守关机前的等待时间:

     #--- set the time to wait before shutdown countdown = 30 
  4. 通过命令测试运行它:

     python3 /path/to/run_close.py 

    使用所有选项对其进行测试:按Enter键立即关闭,无人值守关闭并通过鼠标移动来中断该过程

  5. 如果一切正常,请将其添加到快捷键:选择:系统设置>“键盘”>“快捷方式”>“自定义快捷方式”。 单击“+”并添加命令:

      python3 /path/to/run_close.py 

编辑

下面是不需要任何其他设置的脚本版本。 无论屏幕的分辨率如何,它都会计算退出按钮的坐标。

设置几乎相同,但可以跳过[3.]

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

说明

用于关闭系统的会话管理器窗口的大小始终居中且具有固定(绝对)大小,与屏幕的分辨率无关。 因此, 相对于屏幕中心的位置是恒定因子。

我们需要做的就是读取屏幕的分辨率并从那里计算按钮的位置。

应用函数( get_qloc() )计算左屏幕的分辨率,因为这是对话框出现的分辨率。

注意

time.sleep(0.4)行中设置的时间设置为相对较慢的系统,以确保在关闭窗口出现移动鼠标。 在速度更快的系统上,它可以更短,在较慢的系统(如可能是VM)上可能需要设置更长的时间。