Bash 程序在第二个显示器上打开文件

Bash 程序在第二个显示器上打开文件

我在 bash 中编写了一个小脚本,可以打开一个文件,然后五分钟后关闭它。它会不断重复这个过程。

问题是,无论鼠标指向哪里,程序都会打开,我希望它在我的第二台显示器上打开,该显示器的尺寸非常适合查看文件。

我尝试以以下方式(在命令行)使用显示变量:export DISPLAY=:0.1。但此后我从 CLI 调用的任何程序都会返回错误。(错误:无法打开显示:0.1)

有人有建议吗?

编辑:

这是每五分钟打开一个名为 thesis.pdf 的文件的脚本

#! /bin/bash

while true; do
    evince /home/adam/Desktop/Thesis.pdf &
    sleep 5m
    ps -ef | grep "Thesis.pdf" | awk '{print $2}' | xargs kill
done

exit 0

答案1

要定位窗口,您可以使用操纵 X 事件的工具,例如xdotoolwmctrl。例如,对于wmctrl,您可以使用-e

   -e <MVARG>
          Resize  and  move  a  window  that  has been specified with a -r
          action according to the <MVARG> argument.
   <MVARG>
          A move and resize argument has the format 'g,x,y,w,h'.  All five
          components are integers. The first value, g, is the  gravity  of
          the  window,  with  0  being  the most common value (the default
          value for the window). Please see  the  EWMH  specification  for
          other values.

          The four remaining values are a standard geometry specification:
          x,y is the position of the top left corner of  the  window,  and
          w,h  is  the  width and height of the window, with the exception
          that the value of -1 in any position is interpreted to mean that
          the current geometry value should not be modified.

您通常可以忽略重力,因此要将窗口放置在屏幕左上角并使其尺寸为 1200 x 700 像素,您可以运行:

wmctrl -r :ACTIVE: -e 1,1,1,1200,700

-r您选择一个窗口,:ACTIVE:意味着当前聚焦的窗口。

您还可以简化脚本。没有必要解析ps,特殊变量$!保存最近放置在后台的作业的 PID。无论如何,解析ps通常会失败,因为可能有多个进程与 匹配Thesis.pdf。总会有两个:evincegrep Thesis.pdf您刚刚运行的 。

因此,考虑到所有这些,您可以这样做:

#! /bin/bash
while true; do
    ## Open the pdf
    evince ~/doc/a.pdf &
    ## Save the PID of evince
    pid="$!"
    ## Wait for a 1.5 seconds. This is to give the window time to
    ## appear. Change it to a higher value if your system is slower. 
    sleep 1.5
    ## Get the X name of the evince window
    name=$(wmctrl -lp | awk -vpid="$pid" '$3==pid{print $1}')
    ## Position the window
    wmctrl -ir "$name" -e 1,1,1,1200,700
    ## Wait
    sleep 5m
    ## Close it
    kill "$pid"
done

请注意,我删除了exit 0,因为由于您的while true,它永远不会到达,并且没有意义。您可以使用位置参数来确定要将窗口放置在何处。

最后,关于 的注释DISPLAY。此变量指向 X 显示器。这不是屏幕,而是活动的 X 服务器。许多用户可能在一台机器上运行并行 X 服务器,这允许您选择窗口应显示在哪个服务器上。它与连接的物理屏幕数量完全无关,除非每个屏幕都在运行单独的 X 会话。

答案2

这个答案假设你正在使用 Unity:

编写脚本在特定屏幕或位置打开应用程序时会遇到什么问题

如果你想调用一个应用程序,随后将其窗口放置在特定的位置和大小,则呼叫应用程序和窗口实际出现,是必不可少的,但不可预测;如果您的系统被占用,则该时间可能比空闲时长得多。

您需要一种(最好是“智能”)方法来确保定位/调整大小在窗口出现后(立即)完成。

下面的脚本(编辑版这个) 会在桌面的任意位置(第二个显示器上)打开一个应用程序,可能以文件作为参数。它会等待窗口出现,然后再将窗口移动到其位置和大小,因此无论您的系统是否缓慢(或占用),它都会正确运行。

剧本

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

app = (" ").join(sys.argv[5:])

get = lambda x: subprocess.check_output(["/bin/bash", "-c", x]).decode("utf-8")
ws1 = get("wmctrl -lp"); t = 0
subprocess.Popen(["/bin/bash", "-c", app])

while t < 30:      
    ws2 = [w.split()[0:3] for w in get("wmctrl -lp").splitlines() if not w in ws1]
    procs = [[(p, w[0]) for p in get("ps -e ww").splitlines() \
              if app in p and w[2] in p] for w in ws2]
    if len(procs) > 0:
        w_id = procs[0][0][1]
        cmd1 = "wmctrl -ir "+w_id+" -b remove,maximized_horz"
        cmd2 = "wmctrl -ir "+w_id+" -b remove,maximized_vert"
        cmd3 = "xdotool windowsize --sync "+procs[0][0][1]+" "+sys.argv[3]+"% "+sys.argv[4]+"%"
        cmd4 = "xdotool windowmove "+procs[0][0][1]+" "+sys.argv[1]+" "+sys.argv[2]
        for cmd in [cmd1, cmd2, cmd3, cmd4]:   
            subprocess.call(["/bin/bash", "-c", cmd])
        break
    time.sleep(0.5)
    t = t+1


如何使用它

  1. 安装xdotoolwmctrl。我使用了两个都因为调整大小wmctrl可能会导致(具体来说)出现一些特殊情况Unity

    sudo apt-get install wmctrl
    sudo apt-get install xdotool
    
  2. 将下面的脚本复制到一个空文件中,将其保存为setwindow(无扩展名)~/bin;如有必要,创建目录。

  3. 使脚本可执行(!)
  4. 如果您刚刚创建~bin,请运行:source ~/.profile
  5. 使用以下命令测试运行脚本(例如)

    setwindow 0 0 50 100 gedit /path/to/file.txt
    

    换句话说:

    setwindow <horizontal-position> <vertical-position> <horizontal-size (%)> <vertical-size (%)> <application> <file_to_open>
    

如果一切正常,请在需要的地方使用该命令。

在右侧显示器上打开应用程序

如果您连接了第二台显示器,您应该将组合屏幕视为一个大的虚拟桌面,如下例所示。

在此处输入图片描述

在这个例子中,为了将窗口放在右侧屏幕上,您只需使其 x 位置大于左侧屏幕的 x 分辨率。(在这种情况下 > 1680)。

要以最大化方式使用应用程序打开文件,请将和都<horizontal-size (%)>设置<vertical-size (%)>100

小问题

wmctrl在 Unity 中,当您使用或(重新)定位和(重新)调整窗口大小时xdotool,窗口将始终与屏幕边框保持较小的间距,除非您将其设置为 100%。您可以在上图 (3) 中看到;当窗口inkscape放置在x位置 0 时,您仍然可以看到 Unity Launcher 和窗口之间的微小间距inkscape

答案3

我在这里进行绝对的盲目尝试,但现在的解决方法可能是使用这个脚本:

#!/bin/bash
# Author: Andrew Martin
# Credit: http://ubuntuforums.org/showthread.php?t=1309247
echo "Enter the primary display from the following:"            # prompt for the display
xrandr --prop | grep "[^dis]connected" | cut --delimiter=" " -f1    # query connected monitors
read choice                             # read the users's choice of monitor
xrandr --output $choice --primary                   # set the primary monitor

我相信这对我来说是有效的,将我的中间显示器而不是我的笔记本电脑显示器设置为“主显示器”。理论上,这会在主显示器中打开你的程序?--我知道你说它会在鼠标所在的位置打开,但这有点困难...

希望您能解决它:)

相关内容