Hlavní navigace

Automatické ovládání aplikací s GUI využitím nástroje xdotool

4. 2. 2021
Doba čtení: 19 minut

Sdílet

Popíšeme si, jak ovládat aplikace s grafickým uživatelským rozhraním s využitím nástroje nazvaného xdotool. Tato utilita dokáže simulovat stisky kláves, operace prováděné s myší, operace s celými okny atd.

Obsah

1. Automatické ovládání aplikací s GUI využitím nástroje xdotool

2. Instalace nástroje xdotool

3. Kontrola instalace

4. Simulace stisku kláves

5. Pouhý stisk či puštění klávesy

6. Interaktivní výběr okna pro další operace

7. Programový výběr okna na základě zadaných kritérií

8. Simulace stisku kláves ve vybraném okně

9. Otestování vybraných operací s využitím dalšího nástroje xev

10. Stisk kláves a nástroj xev

11. Kombinace několika operací

12. Výběr okna pro provedení další operace

13. Simulace práce s myší

14. Přesun myši na zadané souřadnice

15. Příkazy provedené v případě změny stavu okna

16. Nastavení související se správcem oken a pracovními plochami

17. Získání geometrie okna (rozměry a umístění na pracovní ploše)

18. Poznámka na závěr

19. Odkazy na Internetu

1. Automatické ovládání aplikací s GUI využitím nástroje xdotool

Unixové systémy a od nich odvozené operační systémy (mezi něž patří především Linux apod.) jsou používány mj. i z toho důvodu, že umožňují relativně snadnou automatizaci mnoha operací s využitím skriptů, které mohou nahradit ruční zadávání jednotlivých příkazů a popř. přenos dat mezi nimi. Primárně je skriptování doménou takových nástrojů a utilit, jejichž vstupní či výstupní data jsou reprezentována textovými či (v poněkud menší míře) binárními daty. Mnohdy je však užitečné skriptovat (či nějakým způsobem automatizovat) i ty aplikace, které jsou vybaveny grafickým uživatelským rozhraním a ovládají se s využitím klávesnice a myši, popř. pomocí podobně koncipovaných vstupních zařízení (touchpad, trackball atd.). Dnes se s jedním takovým nástrojem seznámíme. Jedná se o univerzální nástroj, který nepředpokládá, že daná aplikace s GUI je vybavena například rozhraním pro některé skriptovací jazyky (což je případ GIMPu s rozhraním pro jazyk Scheme a taktéž pro Python).

Pro automatizaci některých operací, které jsou běžně prováděny interaktivně uživatelem (tedy primárně pomocí klávesnice a myši) je možné použít nástroj nazvaný příznačně xdotool, s jehož jednotlivými operacemi se seznámíme v dnešním článku. Tento nástroj naprogramovaný primárně v C, jenž je volatelný přímo z příkazové řádky a tím pádem i z BASH skriptů atd., umožňuje provádět mj. i následující operace:

  1. Simulace stisku klávesy, popř. klávesy s modifikátorem
  2. Simulace buď pouze stisku či naopak puštění klávesy
  3. Simulace psaní delšího textu (tedy sekvence alfanumerických kláves)
  4. Interaktivní výběr okna pro prováděné operace
  5. Automatický výběr okna pro prováděné operace na základě zadaného kritéria
  6. Simulace stisku vybraného tlačítka myši
  7. Simulace pohybu ukazatelem myši
  8. Další operace s vybraným oknem, například jeho minimalizace apod.
  9. Naprogramování akce, která se má provést při změně stavu okna (najetí myší apod.)
Poznámka: pokud budete potřebovat volat xdotool z jiných programovacích jazyků (tedy nikoli pouze ze shellu), je vhodné se poohlédnout po rozhraních k těmto jazykům. V případě Pythonu se například jedná o dnes již poněkud zastaralou knihovnu nazvanou python-libxdo. Pro mnoho účelů – zejména pro tvorbu testů – je však výhodnější použít balíček PyAutoGUI, s nímž se pravděpodobně seznámíme v samostatném článku.

V navazujících kapitolách se sice zaměříme primárně na popis vybraných možností nástroje xdotool, ovšem v souvislosti s tímto nástrojem se seznámíme (i když pouze ve stručnosti) s některými dalšími užitečnými nástroji, především s utilitami nazvanými xwininfo a xev.

2. Instalace nástroje xdotool

Před pokusy s nástrojem xdotool je pochopitelně nutné ho nainstalovat. Jedná se o z dnešního pohledu velmi malý nástroj založený na knihovně libxdo a na systémech založených na RPM ho můžeme nainstalovat následovně:

# dnf install xdotool
 
Last metadata expiration check: 2:51:10 ago on Sat 30 Jan 2021 07:43:07 AM EST.
Dependencies resolved.
===============================================================================================================================================================
 Package                       Architecture                 Version                                       Repository                                      Size
===============================================================================================================================================================
Installing:
 xdotool                       x86_64                       1:3.20150503.1-10.fc32                        beaker-Fedora-Everything                        52 k
Installing dependencies:
 libxdo                        x86_64                       1:3.20150503.1-10.fc32                        beaker-Fedora-Everything                        38 k
 
Transaction Summary
===============================================================================================================================================================
Install  2 Packages
 
Total download size: 90 k
Installed size: 175 k
Is this ok [y/N]: y

Druhá část instalace:

Downloading Packages:
(1/2): libxdo-3.20150503.1-10.fc32.x86_64.rpm                                                                                  684 kB/s |  38 kB     00:00
(2/2): xdotool-3.20150503.1-10.fc32.x86_64.rpm                                                                                 851 kB/s |  52 kB     00:00
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                          1.4 MB/s |  90 kB     00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                                                       1/1
  Installing       : libxdo-1:3.20150503.1-10.fc32.x86_64                                                                                                  1/2
  Installing       : xdotool-1:3.20150503.1-10.fc32.x86_64                                                                                                 2/2
  Running scriptlet: xdotool-1:3.20150503.1-10.fc32.x86_64                                                                                                 2/2
  Verifying        : libxdo-1:3.20150503.1-10.fc32.x86_64                                                                                                  1/2
  Verifying        : xdotool-1:3.20150503.1-10.fc32.x86_64                                                                                                 2/2
 
Installed:
  libxdo-1:3.20150503.1-10.fc32.x86_64                                          xdotool-1:3.20150503.1-10.fc32.x86_64
 
Complete!

Instalace na systémech založených na .deb balíčcích se provede sice jiným příkazem, ale stejně přímočaře:

$ sudo apt-get install xdotool
 
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  libxdo3
The following NEW packages will be installed:
  libxdo3 xdotool
0 upgraded, 2 newly installed, 0 to remove and 401 not upgraded.
Need to get 62,4 kB of archives.
After this operation, 204 kB of additional disk space will be used.
Do you want to continue? [Y/n] y

Druhá část instalace:

Get:1 http://archive.ubuntu.com/ubuntu focal/universe amd64 libxdo3 amd64 1:3.20160805.1-4 [21,0 kB]
Get:2 http://archive.ubuntu.com/ubuntu focal/universe amd64 xdotool amd64 1:3.20160805.1-4 [41,5 kB]
Fetched 62,4 kB in 1s (45,5 kB/s)
Selecting previously unselected package libxdo3:amd64.
(Reading database ... 291087 files and directories currently installed.)
Preparing to unpack .../libxdo3_1%3a3.20160805.1-4_amd64.deb ...
Unpacking libxdo3:amd64 (1:3.20160805.1-4) ...
Selecting previously unselected package xdotool.
Preparing to unpack .../xdotool_1%3a3.20160805.1-4_amd64.deb ...
Unpacking xdotool (1:3.20160805.1-4) ...
Setting up libxdo3:amd64 (1:3.20160805.1-4) ...
Setting up xdotool (1:3.20160805.1-4) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for libc-bin (2.31-0ubuntu9) ...

3. Kontrola instalace

Po instalaci nástroje xdotool se pro jistotu přesvědčíme, že je tento nástroj dostupný a že k němu existuje nápověda:

$ whereis xdotool
 
xdotool: /usr/bin/xdotool /usr/share/man/man1/xdotool.1.gz

Seznam všech dostupných příkazů získáme takto:

$ xdotool --help
 
Available commands:
  getactivewindow
  getwindowfocus
  ...
  ...
  ...
  exec
  sleep

Zobrazit je pochopitelně možné i nápovědu ve formě manuálových stránek, která by taktéž měla být nainstalována:

$ man xdotool
 
XDOTOOL(1)                                                          XDOTOOL(1)
 
NAME
       xdotool - command-line X11 automation tool
 
SYNOPSIS
       xdotool cmd args...
 
       Notation: Some documentation uses [window] to denote an optional window
       argument. This case means that the argument, if not present, will
       default to "%1". See "WINDOW STACK" for what "%1" means.
 
DESCRIPTION
       xdotool lets you programatically (or manually) simulate keyboard input
       and mouse activity, move and resize windows, etc. It does this using
       X11's XTEST extension and other Xlib functions.
 
       There is some support for Extended Window Manager Hints (aka EWMH or
       NetWM).  See the "EXTENDED WINDOW MANAGER HINTS" section for more
       information.
 
KEYBOARD COMMANDS

V navazujících kapitolách si ukážeme, jak lze tento nástroj využít, a to i v prakticky zaměřených příkladech.

4. Simulace stisku kláves

Prvním příkazem poskytovaným nástrojem xdotool je příkaz simulující stisk (a opětovné puštění) klávesy. Tento příkaz se zadává následovně:

$ xdotool key jméno-klávesy

Pokud například budeme chtít simulovat stisk klávesy A (resp. přesněji řečeno Shift+A či a, pokud je aktivní přepínač CapsLock), můžeme na příkazové řádce zadat:

$ xdotool key A
Poznámka: simulovaný stisk klávesy A se projeví v aktivním terminálu, tedy na místě, kde je xdotool zavolán. V praxi to tedy může vypadat následovně:
$ xdotool key A
 
$ A <- je zapsáno nástrojem xdotool a nikoli uživatelem

Lze ovšem použít i mnoho dalších (nealfanumerických) kláves a jejich kombinací, například:

$ xdotool key Ctrl+M

Některá podporovaná jména kláves:

alt+a
ctrl+a
Control_L+a
BackSpace
super+a (alias)
meta+a (alias)
F1
aacute (tedy „á“)

Simulovat je možné i postupný stisk většího množství kláves:

$ xdotool key a b c

Zvětšení pauzy mezi jednotlivými simulovanými stisky (udáváno v milisekundách):

$ xdotool key --delay 500 a b c aacute Ctrl+M
Poznámka: velmi důležitý je přepínač –window, který umožňuje specifikaci okna, do kterého se mají informace o stisku kláves poslat. S tímto přepínačem se seznámíme později v souvislosti s informacemi o ID oken.

Zajistit je možné i simulaci psaní delšího textu:

$ xdotool type Hello world!

Pomalejší psaní s půlsekundovými prodlevami mezi jednotlivými zapsanými znaky:

$ xdotool type --delay 500 Hello world!

5. Pouhý stisk či puštění klávesy

V některých situacích je nutné klávesu či klávesy pouze stisknout a nechat stisknutou/stisknuté. Až po provedení nějaké další operace se klávesa pustí. I tyto dvě činnosti lze velmi snadno simulovat nástrojem xdotool; pouze se namísto volání key jméno-klávesy použije:

$ xdotool keydown jméno-klávesy

Resp. pro opětovné puštění klávesy:

$ xdotool keyup jméno-klávesy

Pokud například zadáme příkaz:

$ xdotool keydown alt

bude se aktivní terminál chovat tak, jakoby byla stále stisknuta klávesa Alt. Mj. to znamená, že po stisku levého tlačítka myši bude možné terminálem pohybovat, ovšem prakticky žádné další operace nebudou plně funkční (až na zkratky vázané na klávesu Alt).

Podobně lze držet stisknutou klávesu Shift:

$ xdotool keydown shift
Poznámka: poměrně často se setkáme s tím, že je klávesa stisknuta a současně se provádí nějaká operace s myší. I tohoto lze dosáhnout s nástrojem xdotool s využitím takzvaného zřetězení příkazů (chaining).

6. Interaktivní výběr okna pro další operace

Všechny předchozí příklady simulovaly stisky i puštění kláves, popř. zápis delší sekvence znaků v okně, které bylo v dané chvíli vybrané (mělo fokus). Typicky se jednalo o okno s terminálem, v němž byl nástroj xdotool spouštěn. V naprosté většině praktických použití xdotool však budeme potřebovat ovládat odlišnou aplikaci, resp. přesněji řečeno odlišné okno (protože aplikace, resp. proces může používat větší množství oken). Okno je možné vybrat ručně nebo automaticky, například na základě jeho jména či dalších kritérií, v každém případě je však výsledkem této operace celočíselný identifikátor okna (který je ovšem odlišný od PID). Nejdříve si ukážeme, jak se okno vybírá ručně. K tomu slouží příkaz:

$ xdotool selectwindow

Pokud tento příkaz zadáte, bude nástroj xdotool čekat na to, až uživatel klikne do okna, jehož identifikátor potřebuje použít a následně tento identifikátor zobrazí na standardním výstupu:

10485776

Podobného efektu můžeme dosáhnout i pomocí jiného nástroje, konkrétně nástroje nazvaného xwininfo:

$ xwininfo
 
xwininfo: Please select the window about which you
          would like information by clicking the
          mouse in that window.

Po výběru okna se vrátí podrobnější informace o vybraném oknu, například:

xwininfo: Window id: 0xa00010 "Xdotool - Keyboard | Linux.org - Mozilla Firefox"
 
  Absolute upper-left X:  0
  Absolute upper-left Y:  22
  Relative upper-left X:  0
  Relative upper-left Y:  22
  Width: 1920
  Height: 1032
  Depth: 24
  Visual: 0x158
  Visual Class: TrueColor
  Border width: 0
  Class: InputOutput
  Colormap: 0xa00002 (not installed)
  Bit Gravity State: NorthWestGravity
  Window Gravity State: NorthWestGravity
  Backing Store State: NotUseful
  Save Under State: no
  Map State: IsViewable
  Override Redirect State: no
  Corners:  +0+22  -0+22  -0-26  +0-26
  -geometry 1920x1032+0+0

V tomto případě se vrátil identifikátor okna v hexadecimální podobě, ovšem xwininfo lze přepnout do režimu, aby vrátil identifikátor reprezentovaný v desítkové soustavě:

$ xwininfo -int

Příklad použití (opět s interaktivním výběrem okna):

$ xwininfo -int
 
xwininfo: Please select the window about which you
          would like information by clicking the
          mouse in that window.

Výsledek nyní bude odlišný:

xwininfo: Window id: 10485776 "Xdotool - Keyboard | Linux.org - Mozilla Firefox"
 
  Absolute upper-left X:  0
  Absolute upper-left Y:  22
  Relative upper-left X:  0
  Relative upper-left Y:  22
  Width: 1920
  Height: 1032
  Depth: 24
  Visual: 0x158
  Visual Class: TrueColor
  Border width: 0
  Class: InputOutput
  Colormap: 0xa00002 (not installed)
  Bit Gravity State: NorthWestGravity
  Window Gravity State: NorthWestGravity
  Backing Store State: NotUseful
  Save Under State: no
  Map State: IsViewable
  Override Redirect State: no
  Corners:  +0+22  -0+22  -0-26  +0-26
  -geometry 1920x1032+0+0

Zajímavé může být i stromové struktury oken, tedy ID nadřazených oken (minimálně se jedná o „kořenové“ okno):

$ xwininfo -tree
 
xwininfo: Please select the window about which you
          would like information by clicking the
          mouse in that window.
 
xwininfo: Window id: 0xa00010 "Automatické ovládání aplikací s GUI využitím nástroje xdotool - Mozilla Firefox"
 
  Root window id: 0x190 (the root window) (has no name)
  Parent window id: 0x6bb4ea (has no name)
     1 child:
     0xa00011 (has no name): ()  1x1+-1+-1  +-1+21
Poznámka: ve všech příkladech bylo vybráno totožné okno, konkrétně okno Firefoxu. Proto jsou všechny ID totožné.

7. Programový výběr okna na základě zadaných kritérií

Častěji se ve skriptech setkáme s požadavkem na programový výběr okna na základě nějakých kritérií. Nejjednodušší je výběr ve chvíli, kdy známe jméno okna (ideálně pokud je jméno jednoznačné). Pokud například běží jediná instance Firefoxu, lze ID okna získat takto:

$ xdotool search "Mozilla Firefox"
 
Defaulting to search window name, class, and classname
10485776

Přesněji řečeno by se měl použít i přepínač –name:

$ xdotool search --name "Mozilla Firefox"
 
Defaulting to search window name, class, and classname
10485776

V některých případech se vrátí více identifikátorů:

$ xdotool search "gvim"
 
Defaulting to search window name, class, and classname
41943041
41943043

Tehdy musíme specifikovat, podle jakého kritéria se má okno vyhledat:

$ xdotool search --name "gvim"
 
35651587

Použít lze i regulární výraz, takže můžeme najít okno GVimu, v němž je editován text tohoto článku, tedy konkrétně soubor „xdotool.htm“:

$ xdotool search --name "xdotool\.htm.*GVIM"
 
35651587

Skutečnosti, že okna lze hledat podle titulku, lze pochopitelně využít, například při vyhledání konkrétního terminálu:

$ xterm -title "Test"

Tento terminál, přesněji ID jeho okna, vyhledáme snadno:

$ xdotool search "Test"
 
Defaulting to search window name, class, and classname
35651618

Nebo korektněji:

$ xdotool search --name "Test"
 
35651618

Výběr všech oken:

$ xdotool search .

Výběr pouze viditelných oken:

$ xdotool search --onlyvisible .

8. Simulace stisku kláves ve vybraném okně

Nyní, když již máme k dispozici mechanismus pro výběr okna na základě jeho celočíselného identifikátoru, můžeme oknu poslat zprávu o stisknuté klávese. Pokud například je ID okna Firefoxu rovno 10485776 (viz předchozí text), můžeme si vynutit překreslení aktuálně vybraného tabu alespoň teoreticky takto:

$ xdotool key --window 10485776 F5

Ve skutečnosti však mnohé aplikace akceptují stisknuté klávesy jen ve chvíli, kdy jsou aktivní. Z tohoto důvodu musíme předchozí příkaz upravit takovým způsobem, aby se nejdříve okno aktivovalo a teprve poté se mu poslal kód stisknuté klávesy:

$ xdotool windowactivate --sync 10485776 key F5

Někdy je zapotřebí po aktivaci okna pozastavit další operaci, například na polovinu sekundy. Následující příkaz otevře v oknu Firefoxu nový prázdný tab:

xdotool windowactivate --sync 10485776 sleep 0.5 key Ctrl+t
Poznámka: pozor na rozdíl mezi kombinací kláves Ctrl+t a Ctrl+T, které jak Firefox, tak i nástroj xdotool rozlišuje!

9. Otestování vybraných operací s využitím dalšího nástroje xev

Většinu funkcí nabízených nástrojem xdotool je možné otestovat s využitím dalšího užitečného nástroje, který se jmenuje xev. Tento nástroj dokáže zobrazit všechny události (event), které jako aplikace běžící pod systémem X přijímá. Kromě událostí, které souvisí s činností vlastního systému oken se jedná i o události spojené s klávesnicí a myší.

Nástroj xev spustíme bez dalších parametrů v jednom terminálu (do kterého se budou vypisovat podrobnější informace o událostech):

$ xev

Mělo by se zobrazit okno přijímající události:

Obrázek 1: Okno nástroje xev.

Povšimněte si, že okno má nápis (titulek) „Event Tester“, takže velmi snadno nalezneme jeho ID:

$ xdotool search "Event Tester"
 
Defaulting to search window name, class, and classname
35651585

10. Stisk kláves a nástroj xev

Následně můžeme tomuto oknu poslat informaci o stisku klávesy „a“:

$ xdotool key --window 35651585 a

Ve skutečnosti tímto způsobem vznikne dvojice událostí – jedna o stisku klávesy:

KeyPress event, serial 36, synthetic YES, window 0x2200001,
    root 0x4006f2c3, subw 0x0, time 0, (1,1), root:(1,1),
    state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (61) "a"
    XmbLookupString gives 1 bytes: (61) "a"
    XFilterEvent returns: False

A druhá o puštění klávesy:

KeyRelease event, serial 36, synthetic YES, window 0x2200001,
    root 0x4006f2c3, subw 0x0, time 0, (1,1), root:(1,1),
    state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (61) "a"
    XFilterEvent returns: False

Můžeme ovšem poslat pouze informaci o stisku klávesy:

$ xdotool keydown --window 35651585 a

Což vede ke vzniku jediné události:

KeyPress event, serial 36, synthetic YES, window 0x2200001,
    root 0x626212c3, subw 0x0, time 0, (1,1), root:(1,1),
    state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (61) "a"
    XmbLookupString gives 1 bytes: (61) "a"
    XFilterEvent returns: False

Puštění klávesy:

$ xdotool keyup --window 35651585 a

To naopak vede ke vzniku této události:

KeyRelease event, serial 36, synthetic YES, window 0x2200001,
    root 0x7d74e2c3, subw 0x0, time 0, (1,1), root:(1,1),
    state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (61) "a"
    XFilterEvent returns: False

Stisk dvojice kláves, typicky Ctrl+klávesa nebo Shift+klávesa se rozloží na několik událostí:

$ xdotool key --window 35651585 shift+a

S výsledkem:

KeyPress event, serial 36, synthetic YES, window 0x2600001,
    root 0xd392a2c3, subw 0x0, time 0, (1,1), root:(1,1),
    state 0x0, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False
 
KeyPress event, serial 36, synthetic YES, window 0x2600001,
    root 0xd392a2c3, subw 0x0, time 0, (1,1), root:(1,1),
    state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (61) "a"
    XmbLookupString gives 1 bytes: (61) "a"
    XFilterEvent returns: False
 
KeyRelease event, serial 36, synthetic YES, window 0x2600001,
    root 0xd392a2c3, subw 0x0, time 0, (1,1), root:(1,1),
    state 0x0, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    XLookupString gives 0 bytes:
    XFilterEvent returns: False
 
KeyRelease event, serial 36, synthetic YES, window 0x2600001,
    root 0xd392a2c3, subw 0x0, time 0, (1,1), root:(1,1),
    state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (61) "a"
    XFilterEvent returns: False

Což je ovšem zcela rozdílné od stisku A:

$ xdotool key --window 35651585 A

S výsledkem:

KeyPress event, serial 36, synthetic YES, window 0x2600001,
    root 0x1345e2c3, subw 0x0, time 0, (1,1), root:(1,1),
    state 0x1, keycode 38 (keysym 0x41, A), same_screen YES,
    XLookupString gives 1 bytes: (41) "A"
    XmbLookupString gives 1 bytes: (41) "A"
    XFilterEvent returns: False
 
KeyRelease event, serial 36, synthetic YES, window 0x2600001,
    root 0x1345e2c3, subw 0x0, time 0, (1,1), root:(1,1),
    state 0x1, keycode 38 (keysym 0x41, A), same_screen YES,
    XLookupString gives 1 bytes: (41) "A"
    XFilterEvent returns: False

11. Kombinace několika operací

Mnohdy je nutné vykonat větší množství operací, které spolu souvisí. Typicky se jedná o získání fokusu okna v kombinaci s nějakou další operací, například se stiskem klávesy. I takovéto kombinace jsou nástrojem xdotool podporovány. Typickým příkladem může být:

$ xdotool windowfocus --sync 35651618 type exit

popř.

$ xdotool windowfocus --sync 35651618 key ctrl+m

Pokud operace windowfocus nepracuje korektně (záleží na mnoha faktorech), lze alternativně vyzkoušet:

$ xdotool windowactivate --sync 41943043 key ctrl+m

Některé operace ovšem snadno zřetězit nelze, což souvisí se zápisem parametrů předávaných nástroji xdotool. V takovém případě se provede spojení na úrovni shellu:

$ xdotool windowfocus --sync 35651618 type exit; xdotool key ctrl+m

Zde není možné za exit přímo zapsat operaci key, protože by byla považována za text (sekvenci znaků), který se má aplikaci poslat.

12. Výběr okna pro provedení další operace

Prozatím jsme ID okna, kterého se nějaká operace týkala, zjišťovali v samostatném příkazu, například následovně:

$ xdotool search --name "Event Tester"
39845889

Ve skutečnosti je však možné ID okna automaticky použít v navazujících příkazech, což je umožněno díky vlastnosti nazvané „window chaining“. Tato vlastnost umožňuje využít ID okna získaného nějakou vyhledávací operací, typicky operací search:

$ xdotool search --name "Event Tester" windowactivate
$ xdotool search --name "Event Tester" key X

Stejně je však možné okno vybrat interaktivně a následně provést naprogramovanou sekvenci příkazů:

$ xdotool selectwindow key X

K ID nalezeného okna je možné se vrátit pseudohodnotou %1:

$ xdotool search --name "Event Tester" key --window %1 X

Ve skutečnosti si nástroj xdotool udržuje zásobník s ID oken odpovídajících vyhledávacím kritériím a hodnotou za % je možné zvolit vhodné okno z tohoto zásobníku, ovšem většinou si vystačíme s prvním nalezeným oknem.

Poznámka: tato hodnota bude použita především při posunu kurzoru myši.

13. Simulace práce s myší

Nástroj xdotool podporuje i simulaci práce s myší. Nejjednodušší je operace napodobující kliknutí vybraným tlačítkem myši. Tato operace se provede příkazem:

$ xdotool click kód-tlačítka-myši

Kde příslušný kód značí:

Kód Operace s myší
1 levé tlačítko myši
2 prostřední tlačítko myši
3 pravé tlačítko myši
4 skrolovací kolečko: směr nahoru
5 skrolovací kolečko: směr dolů
Poznámka: směr skrolování může být i opačný na základě aktuálního nastavení systému.

Stisk pravého tlačítka myši v okně prohlížeče (a tím pádem pravděpodobně zobrazení kontextového menu) zajistí příkaz:

$ xdotool search --name "Mozilla Firefox" windowactivate --sync click 3

Naprosto stejným způsobem je možné skrolovat aktuálně zobrazenou stránkou:

$ xdotool search --name "Mozilla Firefox" windowactivate --sync click 5 click 5

14. Přesun myši na zadané souřadnice

Myš, resp. přesněji řečeno ukazatel myši, je možné posunout na zadané absolutní souřadnice vztažené k levému hornímu rohu desktopu:

$ xdotool mousemove 100 100

Pro posun v rámci nějakého okna je nutné specifikovat ID okna, takže zde využijeme výše zmíněný pseudoparametr %1. Následující příkaz přesune kurzor na souřadnice [100, 100] vztažené k levému hornímu rohu okna prohlížeče:

$ xdotool search --name "Mozilla" mousemove --window %1 100 100

Relativní pohyb myši vztažený k aktuální pozici kurzoru, zajišťuje příkaz mousemove_relative:

$ xdotool mousemove_relative 20 20

Většinou se však tento příkaz používá zřetězený s dalšími příkazy, například:

$ xdotool search --name "Mozilla" mousemove --window %1 --sync 100 100 click --delay 300 3 mousemove_relative --sync 25 15 click --delay 300 1

15. Příkazy provedené v případě změny stavu okna

Zajímavá a potenciálně užitečná je i další vlastnost – možnost specifikace příkazů, které se provedou ve chvíli, kdy se změní stav sledovaného okna nebo oken. K tomuto účelu slouží příkaz behave, za nějž je zapotřebí zapsat trojici parametrů:

  1. ID okna nebo oken, kterých se má příkaz týkat
  2. Změna stavu okna (takzvaná akce)
  3. Příkaz, který se provede ve chvíli, kdy se stav okna skutečně změní

V současné verzi nástroje xdotool jsou podporovány následující změny (akce):

# Označení Význam
1 mouse-enter ukazatel myši najel do plochy okna
2 mouse-leave ukazatel myši opustil plochu okna
3 mouse-click kliknutí myší do plochy okna
4 focus okno získalo fokus (je aktivní)
5 blur okno ztratilo fokus (stává se neaktivní)

Podívejme se nyní na některé možnosti použití příkazu behave. Můžeme například zajistit, aby se po najetí myší do plochy okna toto okno automaticky aktivovalo (získalo fokus). To je pochopitelně operace, kterou dokáže provádět mnoho správců oken, ovšem s využitím nástroje xdotool se toto nastavení může provést pouze pro jediné okno nebo pro sadu oken odpovídajících vyhledávacím kritériím:

$ xdotool search --name "Mozilla" behave %1 mouse-enter windowfocus

Popř. totéž chování pro všechna viditelná okna:

$ xdotool search . behave %@ mouse-enter windowfocus
Poznámka: tento příkaz nikdy automaticky neskončí – nástroj xdotool musíme ukončit například stiskem Ctrl+C v terminálu či příkazem kill.

Vytištění souřadnice ukazatele myši při najetí do libovolného viditelného okna:

xdotool search --onlyvisible . behave %@ mouse-enter getmouselocation
Poznámka: zde se namísto %@ doplní ID viditelných oken.

16. Nastavení související se správcem oken a pracovními plochami

Následuje stručný popis nastavení, které souvisejí se správcem oken. To mj. znamená, že ne všechny následující příkazy budou plně funkční. Pro otestování většiny z nich jsem použil Fluxbox.

Získání počtu pracovních ploch (mezi nimiž se většinou může uživatel nějakým způsobem přepínat):

$ xdotool get_num_desktops
4

Změna počtu pracovních ploch (což například ve Fluxboxu funguje korektně):

$ xdotool set_num_deskops 5

Přepnutí na vybranou pracovní plochu (jsou číslovány on nuly):

$ xdotool set_desktop 1

Získání čísla plochy, na které se nachází hledané okno:

$ xdotool search --name "Mozilla Firefox" get_desktop_for_window
0

Přesun vybraného okna na specifikovanou pracovní plochu:

Hacking tip

$ xdotool search --name "Mozilla Firefox" set_desktop_for_window 3

17. Získání geometrie okna (rozměry a umístění na pracovní ploše)

O vybraném oknu je možné získat i informace o jeho rozměrech, umístění a taktéž pracovní ploše. Například pro webový prohlížeč, který je maximalizován (ovšem obsahuje titulkový pruh – ten leží mimo oblast okna) na první ploše, se mohou vrátit tyto údaje:

$ xdotool search --name "Mozilla Firefox" getwindowgeometry
 
Window 10485776
  Position: 0,44 (screen: 0)
  Geometry: 1920x1032

18. Poznámka na závěr

Pro plnou automatizaci jsou operace poskytované nástrojem xdotool nedostatečné, protože například neumožňují snadno vyhledávat ovládací prvky atd. Pro tento účel se hodí specializovanější nástroje, například již v úvodní kapitole zmíněná knihovna PyAutoGUI, kterou si taktéž popíšeme.

19. Odkazy na Internetu

  1. Xdotool – Keyboard
    https://www.linux.org/threads/xdotool-keyboard.10528/
  2. How to Use Xdotool to Stimulate Mouse Clicks and Keystrokes in Linux
    https://linuxhint.com/xdo­tool_stimulate_mouse_clic­ks_and_keystrokes/
  3. xdootool.1 (manuálová stránka)
    http://manpages.ubuntu.com/man­pages/trusty/man1/xdotool­.1.html
  4. Repositář projektu xdotool
    https://github.com/jordan­sissel/xdotool
  5. Balíček python-libxdo
    https://pypi.org/project/python-libxdo/
  6. Dokumentace k balíčku python-libxdo
    https://rshk.github.io/python-libxdo/library.html
  7. Balíček PyAutoGUI
    https://pypi.org/project/PyAutoGUI/
  8. Dokumentace ke knihovně PyAutoGUI
    https://pyautogui.readthe­docs.io/en/latest/
  9. Píšeme skripty pro grafický editor GIMP (ve Scheme)
    https://www.root.cz/clanky/piseme-skripty-pro-graficky-editor-gimp-ve-scheme/
  10. Use Python to write plug-ins for GIMP
    https://www.ibm.com/develo­perworks/library/os-autogimp/index.html
  11. How do I find the X window ID under the mouse pointer in bash?
    https://unix.stackexchange­.com/questions/16131/how-do-i-find-the-x-window-id-under-the-mouse-pointer-in-bash
  12. xwininfo (manuálová stránka)
    https://www.x.org/releases/X11R7­.7/doc/man/man1/xwininfo.1­.xhtml
  13. xev (manuálová stránka)
    http://manpages.ubuntu.com/man­pages/xenial/en/man1/xev.1­.html
  14. X Window System (Wikipedia)
    https://en.wikipedia.org/wi­ki/X_Window_System

Autor článku

Pavel Tišnovský vystudoval VUT FIT a v současné době pracuje ve společnosti Red Hat, kde vyvíjí nástroje pro OpenShift.io.