如果我在 Okular 中打开同一个文件两次,请切换到现有窗口

如果我在 Okular 中打开同一个文件两次,请切换到现有窗口

我一直很困惑为什么Linux中的文件管理器不能阻止应用程序同时打开同一个文件两次?

具体来说,我想阻止 PDF 文件阅读器 OkularA.pdf在我已经打开该文件时再次打开该文件。我需要收到警告或只显示文件的打开副本A.pdf

更一般地说,我希望任何应用程序都发生这种情况,而不仅仅是 Okular。我想让 Linux 中的文档管理行为与 Windows 中相同。

答案1

文件管理器负责调用应用程序来打开文件。它无法控制应用程序对文件执行的操作,特别是如果您打开同一个文件两次,应用程序是否会打开一个新窗口。

在多个窗口中打开同一文件可能很有用,例如当您想要查看同一文档的不同部分时。因此,系统地拒绝在同一文档上打开多个窗口是很糟糕的。哪种行为是默认行为主要取决于品味。某些应用程序默认打开一个新窗口,其他应用程序默认聚焦于现有窗口。

Okular 默认打开一个新窗口。如果您使用 启动所有实例okular --unique,那么第二次运行该命令时,它不会打开新窗口(尽管它不会聚焦现有窗口,至少在您没有运行 KDE 的情况下)。请注意,第一个实例--unique和第二个实例必须已启动。

Evince,Gnome PDF 查看器,默认为您想要的行为:如果您第二次打开同一文档,它将聚焦于现有窗口。它没有用于打开单独窗口的命令行选项,您必须通过 GUI 来执行此操作(菜单“文件”→“打开副本”或Ctrl+ N)。

答案2

我编写了以下脚本来完成 Okular 的 flatpak 版本的所需行为(我使用的是 LMDE 5)。该脚本基于通过更改窗口标题wmctrl

由于新的欢迎屏幕,获得所需的行为很棘手,但我想我做到了(我不是专家程序员,所以我很欣赏任何改进代码的建议。)

在运行脚本之前,请确保取消选中“在标题栏中显示文档标题(如果可用)”选项,并将选项“不显示文档标题时”设置为“显示完整文件路径”(脚本会更改它,但它需要另外,取消选中“在选项卡中打开新文件”选项。

#!/usr/bin/env bash
# Set expectedwindowtitle whether there is an argument or not, to handle the
# welcome screen: 
if [ -z "$1" ]
then
    expectedwindowtitle="Welcome"
else
    pdfbasename=$(basename "$1")
    pdffullpath=$(dirname "$(realpath "$1")")
    pdfpath=${pdffullpath/#$HOME/\~}
    expectedwindowtitle="$pdfbasename ($pdfpath)"
fi

# Search for a window with the substring "— Okular" in the title (with em-dash, 
# U+2014, that is, untouched), and get its ID and filename:
originaltitle=`wmctrl -l | grep -v "okularjump" | grep -v "grep" | grep -m 1 "— Okular" | awk 'BEGIN{RS="  — Okular"; FS="'$HOSTNAME' "}NF>1{print $NF}'`
originalwindowID=`wmctrl -l | grep -v "okularjump" | grep -v "grep" | grep -m 1 "— Okular" | awk '{ print $1; }'`

# If there is an existent window with the substring "— Okular" (with em-dash) 
# and a filename in the title, then rename it to a new format, as follows: 
# [basemane (short path) – Okular
# Note that the separator in the new format is an en-dash (U+2013) 
if [ ! -z "$originaltitle" ]
then
    originalfullpath=$(dirname "$originaltitle")
    originalbasename=$(basename "$originaltitle")
    originalpath=${originalfullpath/#$HOME/\~}
    newwindowname="$originalbasename ($originalpath) – Okular" # With en-dash 
    wmctrl -r $originaltitle -N "$newwindowname"  
fi

# Search for an already modified window title that matches the expected window 
# title and extract the basename and the path
existentwindowtitle=`wmctrl -l | grep -v "okularjump" | grep -v "grep" | grep "– Okular" | grep -m 1 "$expectedwindowtitle" | awk 'BEGIN{RS=" – Okular"; FS="'$HOSTNAME' "}NF>1{print $NF}'` # With en-dashes

# If expected and existent windows are the same, then switch to the existent 
# window
if [[ "$expectedwindowtitle" == "$existentwindowtitle" ]]
then
    wmctrl -a "$existentwindowtitle"
else
    # There is an argument and nothing to switch to. Then, open the argument with 
    # the new format in the title
    if [ ! -z "$1" ]
    then
        /usr/bin/flatpak run --branch=stable --arch=x86_64 --command=okular --file-forwarding org.kde.okular @@ "$1" @@ &>/dev/null &

        while ! test -n "$argoriginalwindowID"; do
            sleep 0.01
            argoriginalwindowID=`wmctrl -l | grep -v "okularjump" | grep -v "grep" | grep "— Okular" | grep -i -m 1 "$(basename "$1")" | awk '{ print $1; }'`
        done

        pdffullpath=$(dirname "$(realpath "$1")")
        pdfpath=${pdffullpath/#$HOME/\~}
        argWname="$(basename "$1") ($pdfpath) – Okular"
        wmctrl -ir $argoriginalwindowID -N "$argWname"

    else
        # There is no argument and nothing to switch to. Open a welcome screen 
        # with the word Welcome in the title (to make possible to find it later)
        /usr/bin/flatpak run --branch=stable --arch=x86_64 --command=okular --file-forwarding org.kde.okular --title "Welcome" &>/dev/null &
        while ! test -n "$welcomeWname"; do
            sleep 0.01
            welcomeWname=`wmctrl -l | grep -v "okularjump" | grep -v "grep" | grep -m 1 "— Okular" | grep -m 1 "Welcome"`
        done
        originalwindowID=`wmctrl -l | grep -v "okularjump" | grep -v "grep" | grep -m 1 "— Okular" | grep -m 1 "Welcome" | awk '{ print $1; }'`
        newwindowname="Welcome – Okular"
        wmctrl -ir $originalwindowID -N "$newwindowname"
    fi
fi

为了在系统中默认使用该脚本,我将代码保存为 ~/okularjump,使其可执行并将其复制到/usr/bin.然后,我将默认的 .desktop 文件复制到用户文件夹两次:一次是为了运行脚本,另一次是为了隐藏默认的 flatpak 启动器:

chmod +x okularjump
sudo cp okularjump /usr/bin/
cp /var/lib/flatpak/app/org.kde.okular/current/active/export/share/applications/org.kde.okular.desktop ~/.local/share/applications/
cp /var/lib/flatpak/app/org.kde.okular/current/active/export/share/applications/org.kde.okular.desktop ~/.local/share/applications/okular.desktop
echo "Hidden=true" >> ~/.local/share/applications/org.kde.okular.desktop

然后,我将 ~/.local/share/applications/okular.desktop 中的 Exec 行更改为Exec=okularjump %U

最后,我在系统设置中将 Okular 设置为默认 PDF 管理器。

关于打开同一文件的多个实例,仍然可以通过打开对话框从 Okular 打开文件来完成。该脚本将在下次运行时调整窗口标题。

我从 Jumpapp 中获得灵感https://github.com/mkropat/jumpapp(这应该适用于非 Flatpak 版本,但我不确定)和 Flatjumphttps://github.com/ceranco/flatjump(这对我不起作用,但我邀请尝试)。

相关内容