我使用以下脚本(它绑定到键盘快捷键)在 nemo 中打开选定的文件(使用快捷键后单击窗口)。它的作用是从窗口 id(单击窗口后)获取进程 id,然后使用它获取属于 pid 的文件路径。获取文件路径后,它使用 nemo 打开该文件。
#!/bin/bash
WINDOW_ID=$(xdotool getactivewindow)
PID_OF_ACTIVE_WINDOW=$(xdotool getwindowpid $WINDOW_ID)
MY_COMMAND_PATH=$(ps -p $PID_OF_ACTIVE_WINDOW -o command)
# https://stackoverflow.com/q/76028252/1772898
if printf -- '%s\n' "$MY_COMMAND_PATH" | grep -qoP '(file://)?(?<!\w)/(?!usr/).*?\.\w{3,4}+'; then
nemo "$(printf -- '%s\n' "$MY_COMMAND_PATH" | grep -oP '(file://)?(?<!\w)/(?!usr/).*?\.\w{3,4}+')"
fi
但问题出在叶酸上。它使用多个窗口的相同过程。如果我打开多个 .epub 文件,它就会有多个窗口。但是所有的windows都有一个pid。
% xdotool getwindowpid 59418676
15977
% xdotool getwindowpid 59422435
15977
% ps -aux | grep 15977
ismail 15977 0.1 0.7 95405880 128992 ? Sl May05 10:23 /usr/bin/gjs /usr/bin/com.github.johnfactotum.Foliate /media/ismail/SSDWorking/book-collection/_Books/self-development-anxiety-self-talk/child/Freeing Your Child from Anxiety Powerful, Practical Solutions to Overcome Your Childs Fears, Worries, and Phobias (Tamar Chansky Ph.D.).epub
% readlink -f /proc/15977/exe
/usr/bin/gjs-console
我使用的是 Zorin OS 16.2,它使用 Gnome 3。
我检查了子进程,看看是否可以获得其他文件的路径,但没有多大帮助。
% pgrep -P 15977
15995
15998
16011
139458
139662
% ps -p 15995 -o command
COMMAND
/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/WebKitNetworkProcess 7 16
% ps -p 15998 -o command
COMMAND
/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/WebKitNetworkProcess 8 19
% ps -p 16011 -o command
COMMAND
/usr/bin/bwrap --args 29 -- /usr/bin/xdg-dbus-proxy --args=26
% ps -p 139458 -o command
COMMAND
/usr/bin/bwrap --args 58 -- /usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/WebKitWebProcess 59 54
% ps -p 139662 -o command
COMMAND
/usr/bin/bwrap --args 62 -- /usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/WebKitWebProcess 73 58
在 Foliate 中打开文件时,如何从窗口 ID 获取确切的文件路径?
更新1
我做了一些研究。以下命令有效。
% dbus-send --session --print-reply --dest=com.github.johnfactotum.Foliate /com/github/johnfactotum/Foliate org.freedesktop.DBus.Introspectable.Introspect
我还与 d-feet 检查过,d-bus 也显示了窗口。
现在,如果我能以某种方式从这里获取文件路径和窗口 ID,那么它就能解决我的问题。
答案1
Foliate
使用 时,您可以做的是查看窗口名称属性,它似乎包含文档标题,以确定窗口中显示的文件 。您可以从xdotool selectwindow getwindowname
或交互地获取此信息xprop WM_NAME
。
然后,您可以将其包装Foliate
在 shell 脚本中,这样当您运行时,它可以将文件名(或如果以 开头)和等效标题myFoliate myfile.epub
添加到日志文件中。当您稍后选择一个窗口时,您可以获得名称(即标题),并在日志中查找该名称以查找文件名。$PWD/$1
$1
/
获取 epub 文件的标题是可行的:格式是压缩存档,其中<title>
.xml 为toc.ncx
.
相反,你可以运行类似的东西
xdotool search --class 'Foliate' |
xargs -i xdotool getwindowname {}
在脚本开始时获取当前名称/标题的列表,然后Foliate
在后台启动几秒钟后再次获取。新条目将是新标题。
这将无法区分具有相同标题的同一文档的两个版本。相反,您可以在日志中记下新创建的窗口的窗口 ID(仅使用xdotool search --class Foliate
它输出窗口 ID 列表)以及文件名。然后,当您选择窗口时,您将查找该数字,而不是标题。
显然,如果有许多过时的条目,则应使用日志中的最后一个匹配项。
下面是一个可能的脚本实现,myfoliate
它可以使用文件名来调用,或者-q
选择一个窗口并检索文件名。这有点过于复杂,因为我添加了一个锁定机制,以避免在同时打开两个新的 Foliate 窗口时获得错误的 id。这declare -A
使得变量成为windows
一个关联数组,以窗口 id 作为键,这样我们就可以轻松找到新的缺失条目。sleep 2
如果 Foliate 启动缓慢,则可能需要增加。如果可以确定当前没有运行 Foliate,则日志文件可能应该在开始时清空。
#!/bin/bash
log=$HOME/.myfoliate.log
if [ $# -ne 1 ]
then echo "$0: usage: <filename> or -q"
exit 1
fi
if [ '-q' = "$1" ]
then id=$(xdotool selectwindow)
gawk <$log -v id="$id" '
$1==id { $1 = ""; file=$0; }
END{ print file; exit(file==""); }'
exit
fi
if [[ "$1" =~ ^/ ]]
then file=$1
else file=$PWD/$1
fi
listwindows(){
xdotool search --class 'Foliate'
}
( flock -n 9 || exit 2
declare -A windows
for id in $(listwindows)
do windows[$id]=1
done
Foliate "$1" 9>&- &
sleep 2
for id in $(listwindows)
do if [ "${windows[$id]}" == "" ]
then newwin=$id
fi
done
if [ -z "$newwin" ]
then echo "$0: failed"
exit 3
fi
echo "$newwin $file" >&9
) 9>>$log
答案2
是的,这并不是真正可以解决的:每个窗口都属于它自己的进程的假设是完全错误的。
您必须检查 Foliate 是否提供了一些 API,您可以使用这些 API 将窗口映射到该窗口中显示的文件 - 可能没有,中间有很多抽象级别。
所以,简而言之,以你目前的做法,是不可能达到你想要的效果的。
您可以实现一些要求 Foliate 专门将 WID 转换为在该窗口中打开的文档的功能,但这可能需要在 Foliate 代码库中进行认真的开发工作。