---
name: "X11::Protocol::Ext::XTEST"
section: "3pm"
platform: "linux"
package: "perl-x11-protocol-other"
version: "31-6"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/X11::Protocol::Ext::XTEST"
---

# X11::Protocol::Ext::XTEST(3pm)

synthetic user input and more

## NAME

X11::Protocol::Ext::XTEST - synthetic user input and more

## SYNOPSIS

```
 use X11::Protocol;
 my $X = X11::Protocol->new;
 $X->init_extension('XTEST')
   or print "XTEST extension not available";
 $X->XTestFakeInput (name   => 'ButtonPress',
                     detail => 3);  # physical button 3
 $X->XTestFakeInput (name   => 'ButtonRelease',
                     detail => 3);
```

## DESCRIPTION

The XTEST extension provides

- •

  Synthetic keyboard and mouse pointer actions.

- •

  Displayed cursor comparisons.

- •

  Test programs continuing during `"GrabServer"` by other clients.

These things help exercise library or server features which would otherwise require user interaction.

## REQUESTS

The following requests are made available with an `init_extension()`, as per "EXTENSIONS" in X11::Protocol.

```
    my $is_available = $X->init_extension('XTEST');
```

- "($server\_major, $server\_minor) = $X-\>XTestGetVersion ($client\_major, $client\_minor)"

  Negotiate a protocol version with the server.  `$client_major` and `$client_minor` is what the client would like.  The returned `$server_major` and `$server_minor` is what the server will do.

  The current code supports up to 2.1.  The intention would be to automatically negotiate in `init_extension()` if/when necessary.

### Cursor Comparisons

- "$is\_same = $X-\>XTestCompareCursor ($window, $cursor)"

  Return true if the cursor attribute of `$window` is equal to `$cursor`. `$cursor` can be

  - •

    XID (an integer) of a cursor.

  - •

    "None" (or 0).

  - •

    "CurrentCursor" (or 1) for the currently displayed cursor.

  This can be used to check that the cursor attribute of some `$window` is a desired setting, for example

  ```
      $desired_cursor = $X->new_rsrc;
      $X->CreateGlyphCursor ($desired_cursor, ...);
      $X->XTestCompareCursor ($window, $desired_cursor)
        or die "Oops, $window doesn't have desired cursor";
  ```

  Or alternatively, construct a window with a particular cursor and use "CurrentCursor" to check that what's currently displayed is as desired, for example to see if a `GrabPointer()` is displaying what's intended,

  ```
      my $test_window = $X->new_rsrc;
      $X->CreateWindow ($test_window, ...,
                        cursor => $desired_cursor);
      $X->XTestCompareCursor ($test_window, "CurrentCursor");
        or die "Oops, currently displayed cursor is not as desired";
  ```

### Simulated Input

- "$X-\>XTestFakeInput (name=\>...)"

  - "$X-\>XTestFakeInput (\[ name=\>... \])"

  - "$X-\>XTestFakeInput (\[ name=\>\], \[name=\>\], ...)"

  Simulate user input for button presses, key presses, and pointer movement.

  An input action is specified as an event packet using fields similar to `"$X->pack_event()"`.

  `XTestFakeInput()` is always a single user action, so for example a button press and button release are two separate `XTestFakeInput()` requests.  For the core events a single event packet is enough to describe an input but some extensions such as `"XInputExtension"` may require more.

  - Button Press and Release

    The argument fields are

    ```
        name       "ButtonPress" or "ButtonRelease"
        detail     physical button number (1 upwards)
        time       milliseconds delay before event, default 0
    ```

    For example to fake a physical button 3 press

    ```
        $X->XTestFakeInput (name   => 'ButtonPress',
                            detail => 3);
    ```

    `"detail"` is the physical button number, before the core protocol `SetPointerMapping()` translation is applied.  To simulate a logical button it's necessary to check `GetPointerMapping()` to see which physical button, if any, corresponds.

    Be careful when faking a `"ButtonPress"` as it might be important to fake a matching `"ButtonRelease"` too.  On the X.org server circa 1.9.x after a synthetic press the physical mouse doesn't work to generate a release and the button is left hung (presumably in its normal implicit pointer grab).

  - Key Press and Release

    The argument fields are

    ```
        name       "KeyPress" or "KeyRelease"
        detail     keycode (integer)
        time       milliseconds delay before event, default 0
    ```

  - Mouse Pointer Movement

    Mouse pointer motion can be induced with the following.  The effect is similar to a `WarpPointer()`.

    ```
        name       "MotionNotify"
        root       XID of root window, default "None" for current
        root_x     \ pointer position to move to
        root_y     /
        detail     flag 0=absolute, 1=relative, default 0
        time       milliseconds delay before event, default 0
    ```

    `"root"` is the root window (integer XID) to move on.  The default "None" (or 0) means the screen the pointer is currently on.

    ```
        $X->XTestFakeInput (name   => 'MotionNotify',
                            root_x => 123,
                            root_y => 456);
    ```

    `"detail"` can be 1 to move relative to the current mouse position.

    ```
        $X->XTestFakeInput (name   => 'MotionNotify',
                            root_x => 10,
                            root_y => -20,
                            detail => 1); # relative motion
    ```

  - Other Events

    Extension events can be faked after an `init_extension()` so they're recognised by `"$X->pack_event()"`.  It's up to the server or extension which events can actually be simulated.

    If an extension input requires more than one event packet to describe then pass multiple arrayrefs.  For example `"DeviceMotion"` (from `"XInputExtension"`) may need further `"DeviceValuator"` packets,

    ```
        $X->XTestFakeInput ([ name => 'DeviceMotion', ... ],
                            [ name => 'DeviceValuator', ... ],
                            [ name => 'DeviceValuator',  ... ]);
    ```

  For all events `"time"` is how long in milliseconds the server should wait before playing the event.  The default is 0 for no delay.  No further requests are processed from the current client during the delay, so a sequence of `XTestFakeInput()` with delays will execute sequentially with one delay after another.

  Generally the event fields from a `"$X->{'event_handler'}"` function cannot be passed directly to `XTestFakeInput()` to replay it.  In particular,

  - •

    `"time"` from an event is a timestamp, so would have to be zeroed or adjusted to a relative time for a delay in `XTestFakeInput()`.

  - •

    For `"MotionNotify"`, `"detail"` from an event is the hint mechanism, so would have to be zeroed for the absolute/relative flag in `XTestFakeInput()`.

  - •

    For `"ButtonPress"` and `"ButtonRelease"`, `"detail"` from an event is a logical button number after `SetPointerMapping()` transformation, whereas `XFakeInput()` takes a physical number.  A reverse lookup through the `GetPointerMapping()` table would be needed.

### GrabServer Imperviousness

- "$X-\>XTestGrabControl ($impervious)"

  Control the current client's behaviour during a `GrabServer()` by another client.

  If `$impervious` is 1 then the current client can continue to make requests, ie. it's impervious to server grabs by other clients.

  If `$impervious` is 0 then the current client behaves as normal.  Its requests wait during any `GrabServer()` by another client.

## SEE ALSO

X11::Protocol, X11::Protocol::Ext::XInputExtension

[**xdotool**(1)](/xdotool/1.md), X11::GUITest, Xlib [**XTestQueryExtension**(3)](/XTestQueryExtension/3.md)

*/usr/share/doc/x11proto-xext-dev/xtest.txt.gz*, */usr/share/X11/doc/hardcopy/Xext/xtest.PS.gz*

## HOME PAGE

\<http://user42.tuxfamily.org/x11-protocol-other/index.html\>

## LICENSE

Copyright 2011, 2012, 2013, 2014, 2017 Kevin Ryde

X11-Protocol-Other is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.

X11-Protocol-Other is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with X11-Protocol-Other.  If not, see \<http://www.gnu.org/licenses/\>.
