关于x11:是否有Linux命令来确定与给定进程ID相关联的窗口ID?

Is there a linux command to determine the window IDs associated with a given process ID?

给定XX的进程iD,我想有一个任何窗口ID的列表,其中_NET_WM_PID = XX。如果可能的话,最好的办法是最旧的仍处于活动状态的窗口ID。

我对linux还是很陌生,但是我想做的是创建一个使用命令行的脚本,并查看是否已经有一个窗口打开了,该窗口属于使用同一命令行调用的进程。如果是这样,只需将焦点设置在该窗口上,否则执行命令行以进行新的处理。我的意图是在ubuntu桌面上使用此脚本,在该桌面上,我会将这个脚本挂接到我的笔触鼠标手势命令中,这样,例如,每次我为gmail手势时,我都不会获得全新的gmail会话,转到我现有的gmail chrome应用程序窗口。也许有一个更简单的方法可以解决所有这些问题,但是我还没有找到解决方法。

在帮助下,我已经弄清楚了如何使用pgrep为命令行找到PID,以及如何使用wmctrl将焦点设置到窗口句柄,但是我一直坚持从PID到窗口ID。


xwininfo和xprop允许检索您想要的内容,但这有点棘手。

xwininfo允许检索所有已知的窗口,并且xprop可以查询_NET_WM_PID参数的有关单个窗口ID的X。

到目前为止,一种骇人听闻的方法是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

#!/bin/sh

findpid=$1

known_windows=$(xwininfo -root -children|sed -e 's/^ *//'|grep -E"^0x"|awk '{ print $1 }')

for id in ${known_windows}
do
    xp=$(xprop -id $id _NET_WM_PID)
    if test $? -eq 0; then
        pid=$(xprop -id $id _NET_WM_PID|cut -d'=' -f2|tr -d ' ')

        if test"x${pid}" = x${findpid}
        then
            echo"Windows Id: $id"
        fi
    fi
done

结果:

1
2
3
4
5
6
7
8
9
10

mycroft:~ $ ./find_windows.sh 1919
Windows Id: 0x1800748
Windows Id: 0x181b221
Windows Id: 0x1803ad5
Windows Id: 0x181f681
Windows Id: 0x181f658
Windows Id: 0x180006d
Windows Id: 0x1800003
Windows Id: 0x1800001
Windows Id: 0x180001e

如您将看到的,即使您仅在屏幕上看到一个窗口,单个进程也可能具有一定数量的已知窗口。

也许您应该获得这些工具资源,以便做出自己想要的东西。

 相关讨论

  • 谢谢。 当您最初发布该代码时,我就开始研究该代码,但是我陷入了困境,然后陷入困境(因此遗憾地延迟了验收)……不过,这似乎只是出于我的期望。
  • 当您可以轻松选择您感兴趣的窗口时,可以执行此操作的一个衬里(从Patrick偷来)是xwininfo |sed -e s^ * | grep -E"Window id" | awk { print $4 }。 运行不带参数或开关的xwininfo允许您用鼠标选择要了解的窗口。 注意:我必须为RHEL6稍微更改grep命令。


实际上,您也可以使用wmctrl查找PID,我认为这是一种更好的方法。 xwininfo将返回看起来像Windows的各种实体,但是您不会在桌面上真正找到它们。

如果你做男人wmctrl
,您会发现wmctrl -l列出了在桌面上实际可见的所有窗口,以及(最重要的是)它们的窗口ID和标题。 -p添加PID,-x添加窗口类。

正如手册所说(RTFM,对吗?:D),wmctrl也可以搜索其中的一些并激活与搜索匹配的窗口。但是,我不知道是什么决定将返回所有可能的匹配项中的哪一个。另一方面,您可以使用提供的列表功能编写一个包装程序,该包装程序可以更好地进行搜索,并且可能基于其他一些属性(例如,对窗口的最后访问的时间戳),通过查询提供的胜利可以获得该包装器例如,将ID设置为xprop。

下面的这些代码行返回最近的实例的mate-terminal类窗口:

1
2
3
4
5
6
7
8
9

XTIME="_NET_WM_USER_TIME" #a shorter name for xprop query that shoul return timestamps
export TMPDIR=/dev/shm    #save tmp files to memory to make it faster
LST=`mktemp`              #tmp file to store our listing
wmctrl -lx |  awk -F' ' '{printf("%s\t%s    \t",$1,$3); for(i=5;i<=NF;i++) printf("%s",$i); printf("
")  }'  > $LST #pretty-print our listing of windows into the tmp file
 #To each line of listing, prepend a timestamp acquired via an xprop call
 #Use awk to find a line whose 3rd column (winclass) matches the window class"mate-terminal.Mate-terminal" and among those that do, find the one whose timestamp is the largest
while read LINE; do ID=`echo"$LINE"|cut -f 1`; TIME=`xprop -id $ID $XTIME`;  TIME="${TIME/* = /}"; echo -e"$TIME\t$LINE" ; done <$LST ) | awk -v s="mate-terminal.Mate-terminal" '$3 == s {if($1>max){max=$1;line=$0};};END{print line}'
rm $LST  #delete tmp file

无论如何,对于您描述的东西正在构建的东西–如果我是您,我将找出所需命令生成的窗口类别,然后基于该窗口而不是PID进行搜索。或者,您可以假定命令CMD可能会生成带有包含CMD的类名的窗口。

找到线后,应使用窗口ID
通过wmctrl激活窗口。

希望这可以帮助。

旁注:我发现xdotool也可以基于类名和窗口标题进行搜索,但是它非常慢。在我的计算机上,此bash脚本(调用了许多外部实用程序)的速度是xdotool:P的已编译替代方法的10倍。

 相关讨论

  • 但是xdotool的好处是它不需要高级的窗口管理器,因此绝对值得一提。
  • TIME="${TIME* = }"是做什么的?
  • @JanusTroelsen:Bash模式替换,请参阅tldp.org/LDP/abs/html/parameter-substitution.html#EXPREPL1
  • 您可以将上面脚本中的" known_windows ="行替换为known_windows=$(wmctrl -l | sed -e s^\([0-9a-fx]*\).*$\1 | xargs)


这是几种X11窗口管理解决方案(包括一个针对此问题的解决方案)。

Xwininfo和xprop是获取所有窗口ID的好工具,但不是获取与PID关联的主窗口ID的最简单工具(如果可能的话)。要获取主窗口的ID,请通过以下方式使用wmctrl:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

#!/usr/bin/env bash
# getwindidbypid
#
# Get the ID of a window by PID (if the process has a window).
#
# Usage:
#   getwindidbypid <PID>
#

while IFS= read line; do
  if [["${line}" =~ (0x)([0-9a-z]+)([ ][- ][0-9]+[ ])([0-9]*) ]]; then
    winId="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
    pid="${BASH_REMATCH[4]}"
    if [["${pid}" -eq"${1}" ]]; then
      WIND_IDS+=("${winId}")
    fi
  fi
done < <(wmctrl -lp)

if ["${#WIND_IDS[@]}" -gt 0 ]; then
  echo"${WIND_IDS[@]}"
fi

例:

1
2

user ~ $  getwindidbypid 37248
0x05a00012

如果wmctrl找到多个主窗口,则此解决方案将打印多个Window ID。要仅返回第一个,只需将echo"${WIND_IDS[@]}"中的[@]更改为[0]。


您可以使用:

1

xdotool getwindowfocus getwindowname

(原样:您不需要用任何东西替换那些听起来不错的名称。)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值