如何使用 xprop 设置自定义属性并在一行中打开该程序?

如何使用 xprop 设置自定义属性并在一行中打开该程序?

我试过这个:

xprop -id $(gedit & echo $!) -f MY_VAR1 8s -set MY_VAR1 MyCustomVar

我尝试 xprop 并单击 gedit 窗口 - MY_VAR1 不存在。

所以我想也许我应该在那里睡觉......我尝试过:

xprop -id $(gedit & sleep 5 & echo $!) -f MY_VAR1 8s -set MY_VAR1 MyCustomVar

等了 5 秒,尝试了 xprop 并点击了新窗口..仍然没有任何结果

谢谢

答案1

正如 Jeff 指出的那样,PID 和窗口号是不同的东西,并且有将一个映射到另一个并不总是一种简单的方法— 有些进程没有窗口,有些进程共享一个窗口,而其他进程仍然有许多窗口(至少它们在 X 级别上是这样,即使您只看到一个窗口)。

当我开始时,gedit我有一个可见的窗口,但有 3 个离散的 X Windows ( xwininfo -root -tree -all),其名称或类为“gedit”,其中之一是窗口管理器窗口(我使用 fvwm2,您的可能不同),其中之一是“客户端” Leader”,以及多达 20 个其他匿名“窗口”,它们实际上是用户界面的一部分(取决于gedit版本、选项卡数量和 GTK+)。

为了部分解决协调问题,您可以使用属性_NET_WM_PIDWM_CLIENT_LEADER,这些应该保存所属进程的 PID,以及有多个窗口的领导者 ID(尽管后者实际上是为了会话管理,这可能对这里有帮助)。现在,可能存在一些问题_NET_WM_PID,它要求进程和窗口管理器行为正确,但一般来说,在现代桌面上,这应该是可靠的(除了一些旧程序,例如rxvt)。想想像环境变量这样的属性,它应该被设置为 PID,但没有任何强制执行这一点,尽管我相信一些 WM 比其他 WM 更主动。

通常,对于此类问题,您可以编写一个简短的脚本来枚举 Windows ,在循环中gedit查询属性以获取刚刚启动的进程的 PID,然后设置该属性。_NET_WM_PID然而,一切都会密谋反对你:

  • 没有包含窗口 ID 的 X 属性
  • xprop奇怪的是,它无法输出您查询的窗口的 ID
  • 窗口名称根据gedit打开的内容而变化,xprop不支持通配符/模式,并且不会按窗口类别匹配
  • 两者xwininfoxprop仅输出匹配(例如 by -name)的第一个窗口,而不是所有窗口,并且都不易于解析输出
  • X“窗口”的数量可以超过可见的窗口扩大 50 倍
  • gedit默认情况下作为单个进程运行,因此如果您启动第二个进程,gedit该进程将在与主进程接触后立即退出。但是,在最新版本中,您可以用来gedit -s运行独立的进程/窗口。

xdotool这就是诸如、xwit和之类的实用程序存在的原因wmctl;-) 不幸的是,即使没有任何帮助,这些实用程序也无法完全做到这一点。

如果您正在运行独立实例,这将起到作用,作为 shell 脚本,因此它是可以理解的(并且支持文件名参数):

#!/bin/bash
gedit  -s "$@" &
_pid=$!
_wid=$(xdotool search --sync --onlyvisible --pid $_pid)
xprop -f MY_VAR1 8s -set MY_VAR1 MyCustomVar -id $_wid
# xprop -id $_wid MY_VAR1  ## for testing

这用于xdotool执行繁重的工作,在“同步”模式下为窗口提供启动和设置属性的时间,因此gedit -s该过程是独立的且长期存在的,而不仅仅是移交给现有实例然后消失(留下xdotool闲逛)。

或者等效的一句:

gedit -s & xdotool search --sync --onlyvisible --pid $! | 
   xargs -r xprop -f MY_VAR1 8s -set MY_VAR1 MyCustomVar -id

注意到:

  • xdotool可以通过PID搜索,也可以通过名称设置一些属性,但不能根据需要设置任意属性名称
  • xprop搜索和输出选项较差
  • xdotool输出十进制窗口 ID,xprop接受十进制或十六进制
  • 没有太多错误处理

可以不使用 来执行此操作xdotool,但您可能最终会陷入混乱,需要列出系统上的每个窗口并依次处理每个窗口。我试过了,粘贴在这里太丑了:-)

另一种方法是:标准 GTK+ 客户端允许您通过命令行选项设置属性,即使应用程序没有记录它们 ( gedit --help-gtk)。遗憾的是不是任意属性,但您可以将“Class”设置为任意字符串。由于该类是一个多值属性,每个窗口仍将具有“gedit”类(因此如果以这种方式选择,设置/资源仍将应用于它,但它可以阻止应用“Gedit”设置,尽管这可以也有优势)。

$ gedit --class MyCustomVar
$ xprop -notype -name gedit WM_CLASS _NET_WM_PID
WM_CLASS = "gedit", "MyCustomVar"
_NET_WM_PID = 1517
WM_NAME = "gedit"

还有一些用于窗口/进程映射的其他选项(在/proc/PID/environfor中进行搜索WINDOWID,尽管这仅适用于由遵守该约定的终端仿真器启动的进程;或者可能写一个gedit插件)但两者都没有吸引力。也可以看看https://stackoverflow.com/questions/151407/how-to-get-an-x11-window-from-a-process-id- 更有趣的答案之一有一个LD_PRELOADhack 包装的链接XCreateWindow()和几个其他 API 函数来设置任意属性。

相关内容