xdotool: How to search for window by title and class with different patterns (similar to AutoHotkey)

38,116

Solution 1

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.

Solution 2

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

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

Solution 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 %@ | uniq | 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 (|): (uniq left out)

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 %@ | uniq | 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!

Solution 4

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.

Share:
38,116

Related videos on Youtube

t7ko
Author by

t7ko

Updated on September 18, 2022

Comments

  • t7ko
    t7ko 9 months

    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.
  • t7ko
    t7ko over 7 years
    yeah, sorry, a misprint, I meant --name and --class. Will fix now.
  • Gonki
    Gonki over 5 years
    @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.
  • t7ko
    t7ko about 5 years
    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".
  • gokhan acar
    gokhan acar almost 5 years
    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.
  • david.perez
    david.perez almost 5 years
    wmctrl -lx does provide the class.
  • Shanness
    Shanness almost 3 years
    Just a tip for anyone using this, it's 6x faster for me with a uniq to avoid duplicating the 2nd search xdotool search --onlyvisible --class "Google-chrome" getwindowpid %@ | uniq | xargs -I{} xdotool search --all --pid {} --name ""todoist"
  • Volker Siegel
    Volker Siegel almost 3 years
    @Shanness Right, thank you! I added it.
  • FantomX1
    FantomX1 over 2 years
    this is a way to go, lovely, I lost this reply but found it again, so have to comment