X11::P...::XTEST(3pm)

๐Ÿ“ฆ
version 31 ยท 7 versions
, in debian bookworm, debian trixie, ubuntu jammy, ubuntu noble

๐Ÿ’– X11::P...::XTEST(3pm) โ€” aka X11::Protocol::Ext::XTEST ๐Ÿ’–

okay bestie, gather round, because this is the User Contributed Perl Documentation page for the XTEST extension and it is lowkey iconic. no cap.


โœจ 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);

like, you literally fake a whole button click and the X server is fooled. it's giving puppet master energy. ๐Ÿ’…


๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

so what does the XTEST extension actually do for you, bestie? it 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. so instead of sitting there poking your actual mouse like a peasant, you let the code do it. slay. โœจ


๐Ÿ‘‘ 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. it's giving "talking it out" fr fr. ๐Ÿซถ

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. the way that one action = one request is so structured of it. ๐Ÿ’…

๐ŸŒธ 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. iykyk. ๐Ÿง 

โš ๏ธ 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). not me warning you about a hung button bestie โ€” this is real. ๐Ÿ˜ญ

๐ŸŽ€ 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. no promises, bestie. ๐Ÿ™ˆ

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. queue behaviour fr fr. โณ

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.

like, you can't just copy-paste an event back in. it's giving "close but not quite". ๐Ÿ’€

๐ŸŒˆ 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), X11::GUITest, Xlib XTestQueryExtension(3)

/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/>. ๐Ÿ›๏ธ


and that's the whole thing, bestie โ€” this page came from perl v5.28.1, dated 2019-08-26, in the X11::P...::XTEST(3pm) manual. go forth and fake some inputs responsibly. mwah. ๐Ÿ’–โœจ๐Ÿ‘‘

๐Ÿ“ฆ where this page comes from