4

I use the following script (it is bound to a keyboard shortcut) to open selected file (clicking on a window after using the shortcut) in nemo. What is does is from window id (after clicking on the window), it get the process id, then using that get the file path that belong to the pid. After acquiring the file path, it opens that file with 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

But the problem is with Foliate. It use the same process for multiple windows. If I open multiple .epub files, it has multiple windows. But all the windows have one 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

I am using Zorin OS 16.2, which use Gnome 3.

I checked the sub-processes to see if I can get the path of other files, but did not help much.

% 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

How can I get the exact file path from window ID, when file is opened in Foliate?

Update 1

I have done some research. The following command works.

% dbus-send --session --print-reply --dest=com.github.johnfactotum.Foliate /com/github/johnfactotum/Foliate org.freedesktop.DBus.Introspectable.Introspect

I have also checked with d-feet that d-bus also show the windows.

Foliate D-Feet

Now if I could somehow get the file path and window id from here then it would solve my problem.

2 Answers 2

3

What you might do to identify what file is shown in a window when using Foliate, is to look at the window name propery, which seems to hold the document title. You can get this interactively from xdotool selectwindow getwindowname or xprop WM_NAME.

You can then wrap Foliate inside a shell script so that when you run, say, myFoliate myfile.epub it can add to a log file the filename $PWD/$1 (or $1 if it begins /) and the equivalent title. When you later select a window, you can get the name which is the title, and look up this in the log to find the filename.

Getting the title for an epub file is feasible: the format is a zipped archive, with the <title> in xml in toc.ncx.

Instead, you can run something like

xdotool search --class 'Foliate' |
xargs -i xdotool getwindowname {}

at the start of the script to get the list of current names/titles, then again a few seconds after starting Foliate in the background. The new entry will be the new title.

This will not be able to distinguish between two versions of the same document with the same title. Instead, you can note in the log the window-id of the newly created window (using just xdotool search --class Foliate which outputs the list of window-ids), together with the filename. Then when you select the window, you lookup this number, rather than the title.

Obviously, the last match in the log should be used, if there are many out-of-date entries.


Here is a possible implementation as a script, myfoliate, which is called with either a filename, or -q to select a window and retrieve a filename. It is a bit overcomplicated as I added a locking mechanism to avoid getting the wrong id if two new Foliate windows are opened at once. The declare -A makes the variable windows an associative array, with the window ids as keys so we can easily find a new missing entry. The sleep 2 may need to be increased if Foliate is slow to start. The log file should probably be emptied at the start if it can be determined that there is no current Foliate running.

#!/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
6
  • This is the correct answer. Can you please give us some code. It will be very helpful for people who later come to find a solution for this problem. May 9 at 18:26
  • 1
    I've added a possible shell script.
    – meuh
    May 9 at 20:31
  • 1
    You might have to replace Foliate with com.github.johnfactotum.Foliate. In my machine to check version of Foliate, i have to run com.github.johnfactotum.Foliate -v. In /home/ismail/.local/share/applications/com.github.johnfactotum.Foliate.desktop i have replaced Exec=com.github.johnfactotum.Foliate %U with Exec=/home/ismail/.dotfiles/.resources/bash-scripts/foliate.sh %U. Now it works like a charm. May 10 at 6:40
  • Just to be clear, I have copied /usr/share/applications/com.github.johnfactotum.Foliate.desktop to /home/ismail/.local/share/applications/com.github.johnfactotum.Foliate.desktop and then edited it. May 10 at 6:42
  • I have answered a question based on your answer. unix.stackexchange.com/a/745519/206574 Please review the answer (and suggest improvement, specially my coding skill is amateur at best, also i am not a native english speaker) and give us a feedback. It would be better if you could give an answer to that question based on our work (improve the code and logic, and also make it more generic). That way this problem of "opening a file on file explorer that is open on a gui app" will have better solution and help other linux users. May 11 at 8:59
2

Yeah, that isn't really solvable: The assumption that each window belongs to a process of its own is simply wrong.

You will have to check whether Foliate offers some API with which you can map windows to the file shown in that window – it probably doesn't, there's quite a few levels of abstractions in between.

So, in short, with your current approach, it's impossible to achieve what you want.

You can possibly implement something that asks Foliate specifically to convert a WID to the document opened in that window, but it might take serious development effort within the Foliate code base.

2
  • 1
    Question updated with image. May 9 at 11:49
  • You will have to check whether that dbus interface offers a call with which you can achieve what you want! May 9 at 12:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .