7

xdotool lets you search for windows using its search subcommand. I need to locate a window, that has class 'gvim' and title containing word 'TODO'. How do I do this?

What I've tried:

  • You can do xdotool search --name --class, but it would only accept one pattern for both name and title.
  • xdotool supports command chaining, but I could not find a way to chain two search calls -- the second one simply overrides first one.
  • xdotool sucks... this is such a simple operation and there's no way to do it elegantly. – Yan King Yin May 21 '18 at 7:04
12

My xdotool help informs me that your two switches are the same (xdotool version 3.20150503.1),

--name          check regexp_pattern agains the window name
--title         DEPRECATED. Same as --name.

and as such doesn't do anything. My xdotool does the same as yours with replacing the window stack, so I did it with a shell script. A shell script doing what you want is delivered below:

pids=$(xdotool search --class "gvim")
for pid in $pids; do
    name=$(xdotool getwindowname $pid)
    if [[ $name == *"TODO"* ]]; then
        #Do what you want, $pid is your sought for PID,
        #matching both class gvim and TODO in title
    fi
done

The asterisks in the if statement is there in order to do a substring match for TODO, so that it can occur wherever in the title.

  • yeah, sorry, a misprint, I meant --name and --class. Will fix now. – t7ko Jan 15 '16 at 13:57
  • @D.S may you tell why xdotool search --class "gedit" would now work for gedit only, but work for any other window? Same story with xprop utility. – Gonki Mar 10 '18 at 3:58
6

I was able to identify short and unix-way solution:

comm -12 \
  <(xdotool search --name  'title-pattern'  | sort) \
  <(xdotool search --class 'class-pattern'  | sort)
3

Here is another solution adhering to the UNIX way!

On first sight, it is not as beautiful as yours, @t7ko:

xdotool search --onlyvisible --class 'gvim' getwindowpid %@ | xargs -I{} xdotool search --all --pid {} --name 'TODO' getwindowgeometry | sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'

But bear with me! There is some hidden beauty in it.

In short, it

  1. has a linear structure, instead of a tree structure, like one instead of two dimensions
  2. uses more well known shell syntax.
  3. does actually answer your question: It locates the window.

(Whether these points are advantages depends on context - let's just ignore this aspect*.)

I will show the same code in more structured layout below, to make it easier to understand step by step.
But note the indentation is to explain the command - it does not indicate nesting or so, all is still a linear UNIX pipeline.

The same command, just split after the pipes (|):

xdotool search --onlyvisible --class 'gvim' getwindowpid %@ |
    xargs -I{} xdotool search --all --pid {} --name 'TODO' getwindowgeometry |
    sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'

The full command, as shown above, gives the pixel location of the gvim window, returning pixel coordinates relative to the top left corner of the current (possibly virtual) screen as x,y, like 42,433, or maybe -5375,-3809 when it's on the first of four by four virtual screens, and the current one is somewhere down on the right side.

For now, I will shorten the command to only find a X11 window ID - maybe that is all what was actually needed by the OP, not sure:

The shortened command pipeline, a separate shell command on each line:

xdotool search --onlyvisible --class 'gvim' getwindowpid %@ |
    xargs -I{} xdotool search --all --pid {} --name 'TODO'

Now, it starts to be readable:

xdotool \
    search --onlyvisible --class 'gvim' \
    getwindowpid %@ |
xargs -I{} \
    xdotool search --all --pid {} --name 'TODO' 

The xdotool command search is used to find windows with the "class" gvim, leaving out some "internal" windows. The result is listed as PID's (process identifiers).
For each PID, xargs runs another xdotool search, checking the "name" for our example pattern TODO - after checking for the PID.

(Just in case: The lines ending in \ - called continuation lines - need to actually end with the \ and no whitespace before the newline.)

Now back to the original command:

xdotool \
    search --onlyvisible --class 'gvim' \
    getwindowpid %@ |
xargs -I{} \
    xdotool \
        search --all --pid {} --name 'TODO' \
        getwindowgeometry |
sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'

The remaining part lists some details about the window, including the position. The sed command matches and returns only the x,y position value.

As example, running the command on the top on my 16th virtual screen (of 4 by 4), with a "TODO" gvim on screen 1:

$ xdotool search --onlyvisible --class 'gvim' getwindowpid %@ | xargs -I{} xdotool search --all --pid {} --name 'TODO' getwindowgeometry | sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'
-7653,-4732

*) Disclaimer: I prefer @t7ko's code. A lot!

  • Using --onlyvisible is nice. Helped me with a similar issue. Thunderbird can start with 14 windows and only one or two are on the desktop. I have no idea what the other ones are for. BTW only visible means can be displayed - not just immediately shown on the current desktop. – Joe Aug 27 '18 at 4:39
1

Short and elegant answer (which uses wmctrl):

result=$(wmctrl -l | grep 'TODO - gvim' | grep -Eo '0x[0-9a-f]+')

The resulting window ID is in hex, so you need to convert it to decimal (used by xdotool):

printf "%d\n" $result

Then you can do whatever with xdotool.

  • 1
    wmctrl manual says that -l does not print window class, only title; so your code snippet does not solve my problem "search by title AND class". – t7ko May 22 '18 at 11:26
  • 1
    wmctrl -lx does provide the class. – david.perez Aug 31 '18 at 6:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.